The typename disambiguator is required only if the name is a dependent name
(and for a class template, only if it is not the name of a member of the current instantiation).
See: http://en.cppreference.com/w/cpp/language/dependent_name
You appear to be confused about the clear distinction a parameter and an argument.
1 2 3 4 5 6 7 8
int foo( int number ) ; // number is the parameterconstint x = foo(33) ; // 33 is the argumentint foo( int number = 5 ) ; // number is the parameter, 5 is the default argumenttemplate < typename T > struct bar{ /* ... */ } ; // T is the template-parameter
bar<int> bb ; // int is the template-argumenttemplate < typename T = double > struct bar ; // T is the template-parameter, double is the default template-argument
The typename disambiguator is required only if the name is a dependent name,
(and for a class template, only if it is not the name of a member of the current instantiation).
A dependent name is a name for which the semantics depends on the template-parameters; that is, its meaning may differ between different instantiations of the template.
Template-parameters appear only in the declaration or definition of a templated entity;
ergo dependent names appear only inside a template.
#include <iostream>
#include <string>
#include <type_traits>
#include <vector>
template < typename T > // T is a template type parameterstruct foo
{
// std::remove_reference<T>::type is a dependent name (depends on template parameter T)
// typename disambiguator is required
using value_type = typename std::remove_reference<T>::type ;
// value_type is a dependent name (depends on template parameter T)
// name of a member of the current instantiation: typename disambiguator is not required
//
// std::remove_cv<value_type>::type is a dependent name (depends on template parameter T)
// typename disambiguator is required
using unqualified_value_type = typename std::remove_cv<value_type>::type ;
using iterator_type = typename std::vector<unqualified_value_type>::iterator ;
// iterator_type is a dependent name (depends on template parameter T)
// name of a member of the current instantiation: typename disambiguator is not required
foo( iterator_type iter ) : iter(iter) {}
iterator_type iter ;
};
template <> struct foo<int> // int is not a template-parameter; it is a template-argument
{
using T = int ; // T is not a dependent name
// none of the following involve dependent names
// (there are no dependent names at all in this class: because there are no template-parameters)
using value_type = std::remove_reference<T>::type ;
using unqualified_value_type = std::remove_cv<value_type>::type ;
using iterator_type = std::vector<unqualified_value_type>::iterator ;
foo( iterator_type iter ) : iter(iter) {}
iterator_type iter ;
};
int main()
{
// instantiate foo with template-argument double
// this is not the definition of a templated entity
// there are no dependent names
foo<double> my_foo( {} ) ;
constdecltype(my_foo)::unqualified_value_type v = 7 ;
std::cout << std::fixed << v << '\n' ;
}