Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding typename causes program to fail compilation

Tags:

c++

templates

So I have this code:

#include "type_traits"

struct A{
    int member;
};

struct B{
    typedef A object;
    typedef int member;
};

typedef std::integral_constant<B::member, B::object::*, &A::member> type;

But if I change the final line to:

typedef std::integral_constant<typename B::member, typename B::object::*, &A::member> type;

The program will not compile....

Why does adding the typename specifier cause the program to not compile? This is especially surprising to me because I thought I needed it in this case.

Note: Using gcc 5.1.0

like image 598
DarthRubik Avatar asked Feb 25 '26 08:02

DarthRubik


1 Answers

You cannot add typename everywhere you want to specify a type. You can only, and require to add typename when you use a dependent type name.

A dependent name is something like this:

template<typename T>
void foo() { (void)T::member(); }

Is T::member a type, or a member function named member? The compiler will assume it's not a type by default. If it is a type, you must specify typename to disambiguate.

template<typename T>
void foo() { (void)typename T::member(); }

Now the compiler is told to assume that T::member is indeed a type.

However, the C++ syntax only allow it in cases that the nature of T::member cannot be known. So when dealing with know types, like your code, the compiler already know that these members are types. There's nothing to desambiguate.

If you were to change you typedef by a template alias, it would require typename as you wrote:

template<typename C, typename D> //          v----- Type of pointer to member?
using type = std::integral_constant<typename D::member D::object::*, &C::member>;
//        Here, D::object::* don't need typename,  ----^
//        since only types are allowed here
like image 68
Guillaume Racicot Avatar answered Feb 27 '26 20:02

Guillaume Racicot