When to use "typename" in a using declaration?

Hello.

I was looking at the implementation of the std::conditional here >> http://en.cppreference.com/w/cpp/types/conditional

I ended up making my own version of the std::conditional but still I have a doubt: the helper type

1
2
template< bool B, class T, class F >
using conditional_t = typename conditional<B,T,F>::type;


Why is that typename required?

I read in the C++ Programming Language (Stroustrup's book) that it's there to ensure that what comes after is a type

Ok, but why then the following is allowed:

 
using c = char;


Of course here there's no template involved...

But the using declaration REQUIRES a type because of its nature!

1
2
3
int a = 10;

using A = a;


This of course won't work because a isn't a type but a variable.

So if we can use the USING directive only with types, why would I need to specify it with typename?

Thanks in advance!
A (slightly simplified) explanation:

In a template that we write, there are two kinds of names that could be used - dependant names and non- dependant names. A dependant name is a name that depends on a template parameter; a non- dependant name has the same meaning irrespective of what the template parameters are. For example:
1
2
3
4
5
template< typename T > void foo( T& x, int value )
{
    ++ T::static_member_variable ; // 'static_member_variable' is a dependant name
    ++value ; // 'value' is a non- dependant name
}


What a dependant name refers to could be something different for each different instantiation of the template. As a consequence, C++ templates are subject to "two-phase name lookup". When a template is initially parsed (before any instantiation takes place) the compiler looks up the non-dependent names. When a particular instantiation of the template takes place, the template parameters are known by then, and the compiler looks up dependent names.

During the first phase, the parser needs to know if a dependant name is the name of a type or the name of a non-type. By default, a dependant name is assumed to be the name of a non-type. The typename keyword before a dependant name disambiguates it to be the name of a type.

More information: see 'The typename disambiguator for dependent names'
http://en.cppreference.com/w/cpp/language/dependent_name
Thanks for the detailed answer!

So you said that when there are dependant names, C++ performs a 2-phase name lookup.

We haven't instantiated the template yet, so the first thing he does is looking for the non-dependent names, since it's the only thing he can work with.

Once we instantiate the template with an actual type (e.g. vector<Entry>) the compiler can finally look for those dependant names.

Now, you said:

During the first phase, the parser needs to know if a dependant name is the name of a type or the name of a non-type


And the question is why?

Why does the compiler worry about that in the FIRST phase, where he only needs to look for non-dependant names?

Why doesn't the compiler start worrying about type or non-type when we actually instantiate the template?
> And the question is why? Why does the compiler worry about that in the FIRST phase,
> where he only needs to look for non-dependant names?

The C++ grammar is heavily context sensitive; for instance: name_a * name_b ; would be multiplication if name_a is the name of a non-type and the declaration of a pointer if name_a is the name of a type.

In normal code, the parser manages this by classifying names: before name_a is used, it must be declared and the parser can keep track of what exactly name_a is.

With templates, the situation becomes more involved: when the template
(say template < typename T > void foo( T& object ) { /* ... T::dependant_name ... */ } is parsed for the first time, the classification for T::dependant_name is not available. In addition, what a dependent name is may be changed by an explicit specialisation, which need not be visible during phase one.

One alternative would have been to avoid two-phase name lookup altogether, and defer look up of all names to the time when the template is instantiated. (Btw, this is more or less what the still-non-conforming-in-this-regard microsoft implementation does.) In addition to being less efficient, this could also lead to edge-cases where the meaning of a non-dependent name (that was intended by the template author) could be changed depending on where the template was instantiated from.

Therefore, the alternative that was adopted is to classify the names in a template into two distinct genres: dependent names and non-dependent names, and to resolve non-dependent names during the first phase (when the template definition is first seen). This would require that we give some minimal context to the parser about what a dependent name is; ergo the need for typename and template disambiguators for dependent names.
Alright everything's clear now. Thank you.

You also said that template is another disambiguator.

I knew it, I read it somewhere... but still it wasn't clear to me.

I've seen an example on Stack Overflow (https://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords)

[i'm referring to the first, accepted answer by Johannes Schaub - litb]

In the boost namespace there's an integer "function" variable set to 0

It's not a template, so the behaviour of boost::function< int() > f; was completely expected...

But if we defined "function" as a template-function and not as an integer... we wouldn't have had this problem.

Yet, the guy says:

What if we can't know yet whether the name is a template when parsing the code?


But how can a compiler not be able to understand whether a name is a template or not?

1
2
3
4
5
6
7
8
9
10
11
12
// Not a template
namespace boost 
{
     int function = 0; 
}

// Template function
namespace boost
{
     template<typename T>
     void function(const T& var) {...}
}


I mean, okay that the compiler can't know whether a dependant name is a type or a non-type.......... but if it can't even understand whether a function/class is a template or not seems a bit strange...


Last edited on
The situation is akin to the case of the dependant name being the name of a type or the name of a non-type. Correctly parsing < and > requires contextual information which is not implicitly available for a dependant name in a template.

Consider these two function templates:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static int bar() { return 22 ; }

template < typename T > auto foo_is_not_a_template()
{
    // not a template; so < and > are the relational operators (less than, greater than)
    return T::foo<34>::bar() ;
    // parsed as ( (T::foo) < 34 ) > ( ::bar() )
    // *** warning *** : these comparisons do not have their mathematical meaning (GNU)
    // *** warning *** : '>': unsafe use of type 'bool' in operation (Microsoft)
}

template < typename T > auto foo_is_a_template()
{
    // template; so < and > are beginning and end of the template argument list
    return T:: template foo<34>::bar() ;
    // parsed as: instantiate the template T::foo<34>,
    // and call the static member bar() of the instantiated class
}


Code example: http://rextester.com/NRAYP95711
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct A { static constexpr int foo = 7 ; } ;

struct B
{
    template < int N > struct foo
    {
        static std::string bar() { return std::string( N, 'k' ) ; }
    };
};

int main()
{
    std::cout << "A: foo is not a template: " << foo_is_not_a_template<A>() << '\n' ; // print integer 0
                                 // ie. ( (A::foo) < 34 ) > ::bar()
                                 // ie. (    (7)   < 34 ) >  (22)

    std::cout << "B: foo is a template: " << foo_is_a_template<B>() << '\n' ; // print string "kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk"
                            // ie. the result of call of the static member function B::foo<23>::bar()
}
That's a more understandable explanation indeed!

So if I've understood correctly, it's the same situation:

T::MyType requires typename to tell the compiler that MyType is actually a type.

T::MyFunction<Object>() requires template to tell the compiler that MyFunction is a template function.

We need to use these two keywords to disambiguate since both MyType and MyFunction are dependant names (they depend from T).

Am I correct? If yes, I think I got it all.

Thank you!
Last edited on
> Am I correct?

Yes.

Without the disambiguators, T::MyType would be parsed as a non-type and
T::MyFunction would be parsed as a non-template.
Topic archived. No new replies allowed.