2

As an example, a singly-linked list node might be defined as follows

namespace example_part1
{
    class node
    {
        node * next;
        int value;
    }
}

assuming we have a list of integers only. This class is allowed to have a member that points to its own type, because pointers all have the same size, regardless of the size of the underlying data structure.

Now, why am I not allowed to do this

namespace example_part2
{
    using node = std::pair<example_part2::node *, int>;
}

?

I know this seems like a silly example, but I want to know more the reason behind why this won't compile. I actually have a similar situation to this where it might be useful (not with std::pair). Also, assume these two code segments are from different programs, i.e. I don't have a node custom class as well as a pair aliased as a node in the same program.

Konrad
  • 2,207
  • 4
  • 20
  • 31
  • 1
    node is going to be a custom class and std::pair at the same time? – Millie Smith Apr 28 '17 at 21:39
  • @MillieSmith please see my edit (addition) to the main question – Konrad Apr 28 '17 at 21:42
  • So based on your edit, is `using node = std::pair;` completely alone? As in, `node` hasn't been defined yet? How's it supposed to know the actual type? When does the recursion end? – Millie Smith Apr 28 '17 at 21:45
  • @MillieSmith the same way in which it knows the actual type in the case of a class? – Konrad Apr 28 '17 at 21:46
  • The recursion ends when you're using classes with pointers. You can construct a node with a null pointer. How do you construct std::pair? `std::pair *, int> *, int>` – Millie Smith Apr 28 '17 at 21:47
  • Assuming `using node = std::pair;` is to be declared inside `struct node`, then that's nonsense. You cannot name any entity with the same name as $the *class-name* inside $the class' body. – WhiZTiM Apr 28 '17 at 21:48
  • @WhiZTiM, I did say in the last paragraph that these are two completely separate code segments. The assumption you made is not correct. – Konrad Apr 28 '17 at 21:50
  • Infinitely recursive definitions are rarely correct. – Donnie Apr 28 '17 at 21:51
  • @KonradKapp, Ok. Just saw your edit. ... You have a name conflict. You may want to simply use a different name, or employ the services of `namespaces` to disambiguate them. – WhiZTiM Apr 28 '17 at 21:51
  • @WhiZTiM thanks, just made the edit. – Konrad Apr 28 '17 at 21:53
  • Note that at http://en.cppreference.com/w/cpp/language/type_alias "abstract declarator or any other valid type-id (which may introduce a new type, as noted in type-id). The type-id cannot directly or indirectly refer to identifier." – Donnie Apr 28 '17 at 22:09
  • @Donnie, make this an answer and I will accept it. Thanks. – Konrad Apr 28 '17 at 22:12

2 Answers2

3

When referring to the specification of type alias declarations at cppreference, the type-id must not directly or indirectly refer to the name that is introduced:

using identifier attr(optional) = type-id ; identifier - the name that is introduced by this declaration, which becomes either a type name template-parameter-list - template parameter list, as in template declaration type-id - abstract declarator or any other valid type-id (which may introduce a new type, as noted in type-id). The type-id cannot directly or indirectly refer to identifier. Note that the point of declaration of the identifier is at the semicolon following type-id.

Concerning namespaces, note that node in std::pair<node *, int> does not refer to node of namespace example_part1 and consequently remains an undefined type name.

Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58
  • Any reasons for the downvotes that help me improving the answer? – Stephan Lechner Apr 28 '17 at 22:02
  • 1
    You completely misunderstood the question. I did say in the last paragraph that those two code segments are completely separate, as if they are from different programs. I then changed the code so that they are in different namespaces, as suggested in the comments, to further clarify. Anyway, thanks for spotting the error in my edit. – Konrad Apr 28 '17 at 22:04
  • I'd guess it's because he probably wants the `node *` in the `pair` to create a pointer to the *alias* he's creating, not a pointer to the `node` in the other namespace. – Nicol Bolas Apr 28 '17 at 22:05
  • 1
    It doesn't answer the question he's asking. – Donnie Apr 28 '17 at 22:05
  • @StephanLechner Good answer eventually, but another person got it first (in the comments section to the original question) before you changed it to the current version. Therefore accepted the other answer instead – Konrad Apr 28 '17 at 22:30
3

Note that at type-alias

[type-id is an] abstract declarator or any other valid type-id (which may introduce a new type, as noted in type-id). The type-id cannot directly or indirectly refer to identifier.

Essentially, aliases may not be recursive.

Donnie
  • 45,732
  • 10
  • 64
  • 86
  • (other than, obviously, I should have just posted an answer at the beginning instead of a comment with the answer.) – Donnie Apr 28 '17 at 22:42