Why Is the Keyword "Typename" Needed Before Qualified Dependent Names, and Not Before Qualified Independent Names

Why is the keyword typename needed before qualified dependent names, and not before qualified independent names?

A name in C++ can pertain to three different tiers of entities: Types, values, and templates.

struct Foo
{
typedef int A; // type
static double B; // value
template <typename T> struct C; // template
};

The three names Foo::A, Foo::B and Foo::C are examples of all three different tiers.

In the above example, Foo is a complete type, and so the compiler knows already what Foo::A etc. refer to. But now imagine this:

template <typename T> struct Bar
{
T::A x;
};

Now we are in trouble: what is T::A? if T = Foo, then T::A = int, which is a type, and all is well. But when T = struct { static char A; };, then T::A is a value, which doesn't make sense.

Therefore, the compiler demands that you tell it what T::A and T::B and T::C are supposed to be. If you say nothing, it is assumed to be a value. If you say typename, it is a typename, and if you say template, it is a template:

template <typename T> struct Bar
{
typename T::A x; // ah, good, decreed typename

void foo()
{
int a = T::B; // assumed value, OK

T::template C<int> z; // decreed template
z.gobble(a * x);
}
};

Secondary checks such as whether T::B is convertible to int, whether a and x can be multiplied, and whether C<int> really has a member function gobble are all postponed until you actually instantiate the template. But the specification whether a name denotes a value, a type or a template is fundamental to the syntactic correctness of the code and must be provided right there during the template definition.

Why typename keyword is not needed in template dependent nested type names in VS2015?

In c++20 typename is not needed there. In some contexts, the need for typename was removed, because syntactically anything there must be a type.

In particular:

A qualified name that appears in type-id, where the smallest enclosing type-id is:

  • the type in a new expression that does not parenthesize its type;

Quoted source isn't directly from the standard, but pretty reliable.

Prior to c++20 typename was needed there; it would be parsed as a value, and new value is not valid syntax. In c++20 typename is optional in that context.

Now, visual-studio-2015 has no c++20 features in it; what you are seeing there is MSVC's failure to properly implement c++11/c++14/c++17, not a c++20 extension.

c++ iterator with template

Add a typename before the iterator

#include <iostream>
#include <vector>

template <class T>
void my_print(std::vector<T> input)
{
for (typename std::vector<T>::iterator pp = input.begin(); pp != input.end(); ++pp)
{
std::cout << *pp << "\n";
}
}
int main(int argc, char* argv[])
{
std::vector<int> aa(10, 9);
my_print(aa);

return 0;
}

source: http://www.daniweb.com/software-development/cpp/threads/187603/template-function-vector-iterator-wont-compile

What are second after function name in template funciton declaration?

template<typename C, typename V> //template declaration
vector<typename C::iterator> //return type (vector of iterators)
find_all //function name
(C& c, V v) //argument list

Function find_all returns vector<typename C::iterator>, or "vector of iterators to C".

The reason why typename is needed is explained in this question: Why is the keyword “typename” needed before qualified dependent names, and not before qualified independent names?


A simpler example, without templates, which also uses <> in return type:

std::vector<int> generateNNumbers(std::size_t numberOfElements)
{
std::vector<int> res;
...
return res;
}

The 'typename' word in C++

In simple words, "dependent name" in a template code is some type which is constructed within the definition of the template.

In your example, the types CVertex, CEdge, CFace, CHalfEdge are template parameters. All other names which are declared with usage of the parameters are dependent.

They can be type names but can be something else, e.g. name of the functions or variables. Compiler has to understand, whether a given dependent name is a type or a variable. It is actually compiler-dependent. To help the compiler, you add "typename" to indicate that this identifier is a type.

Imagine, that your code does not have #include <vector> but instead uses forward declaration:
namespace std { template<class T, class Alloc=allocator<T> > class vector; }

Then compiler has no idea which names within class vector are types and which are member names. It only knows that vector is a type.

For example, in the code typename std::vector<TLoop*> m_loops; most likely the word typename can be omitted for most compilers because they know that vector is a type.

However, the code std::vector<TLoop*>::const_iterator will sure require typename: for (typename std::vector<TLoop*>::const_iterator it = loops().begin(); ...

Hope it helps.

Specifying one of base class template parameters by derived class template parameter. How to use base class's using declarations

myflt_t defined in class a is not visible in class b as explained here: https://eli.thegreenplace.net/2012/02/06/dependent-name-lookup-for-c-templates

You can bring myflt_t into class b by without the explicit re-declaration:

using typename base_t::myfl_t

Using typedef inside template specializations

DataType isn't actually a type. It's a instance of PaddingTrick::Type, which is why the next line is giving you an error. You need to do:

typedef typename PaddingTrick::Type DataType;

How do you understand dependent names in C++

A dependent name is essentially a name that depends on a template argument.

When using templates there is a distinction between the point of definition of the template and the point of instantiation i.e. where you actually use the template. Names that depend on a template don't get bound until the point of instantiation whereas names that don't get bound at the point of definition.

A simple example would be:

template< class T > int addInt( T x )
{
return i + x.toInt();
}

where a declaration or definition of i would need to appear before the definition given above since i does not depend on the template argument T and is therefore bound at the point of definition. The definition of the toInt member of the as-yet-unknown-type x variable only has to appear before the addInt function is actually used somewhere as it is a dependent name ( technically the point of instantiation is taken as the nearest enclosing global or namespace scope just before the point of use and so it has to be available before that ).

non-type template parameter whose type depends on another parameter

You almost put the typename in the right place.

template<typename T, typename A<T>::Pointer P>

Also, the Pointer typedef needs to be public in order for this to work.



Related Topics



Leave a reply



Submit