Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the template argument deduction not working here?

Tags:

c++

templates

I created two simple functions which get template parameters and an empty struct defining a type:

//S<T>::type results in T& template <class T> struct S {     typedef typename T& type; };  //Example 1: get one parameter by reference and return it by value template <class A> A temp(typename S<A>::type a1) {     return a1; }  //Example 2: get two parameters by reference, perform the sum and return it template <class A, class B> B temp2(typename S<A>::type a1, B a2)//typename struct S<B>::type a2) {     return a1 + a2; } 

The argument type is applied to the struct S to get the reference. I call them with some integer values but the compiler is unable to deduce the arguments:

int main() {     char c=6;     int d=7;     int res = temp(c);     int res2 = temp2(d,7); } 

Error 1 error C2783: 'A temp(S::type)' : could not deduce template argument for 'A'

Error 2 error C2783: 'B temp2(S::type,B)' : could not deduce template argument for 'A'


Why is this happening? Is it that hard to see that the template arguments are char and int values?

like image 665
Juan Avatar asked Aug 12 '09 20:08

Juan


People also ask

What is template argument deduction?

Template argument deduction is used when selecting user-defined conversion function template arguments. A is the type that is required as the result of the conversion. P is the return type of the conversion function template.

What is type deduction C++?

Type inference or deduction refers to the automatic detection of the data type of an expression in a programming language. It is a feature present in some strongly statically typed languages. In C++, the auto keyword(added in C++ 11) is used for automatic type deduction.

What is a template argument?

A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.

How many template arguments are there?

1) A template template parameter with an optional name. 2) A template template parameter with an optional name and a default. 3) A template template parameter pack with an optional name.


2 Answers

Just as first note, typename name is used when you mention a dependent name. So you don't need it here.

 template <class T> struct S {     typedef T& type; }; 

Regarding the template instantiation, the problem is that typename S<A>::type characterizes a nondeduced context for A. When a template parameter is used only in a nondeduced context (the case for A in your functions) it's not taken into consideration for template argument deduction. The details are at section 14.8.2.4 of the C++ Standard (2003).

To make your call work, you need to explicitly specify the type:

 temp<char>(c); 
like image 162
Leandro T. C. Melo Avatar answered Sep 19 '22 08:09

Leandro T. C. Melo


It is looks like nondeduced context. According to C++ Standard 14.8.2.4/4:

The nondeduced contexts are:

  • The nested-name-specifier of a type that was specified using a qualified-id.
  • A type that is a template-id in which one or more of the template-arguments is an expression that references a template-parameter.

When a type name is specified in a way that includes a nondeduced context, all of the types that comprise that type name are also nondeduced. However, a compound type can include both deduced and nondeduced types. [Example: If a type is specified as A<T>::B<T2>, both T and T2 are nondeduced. Likewise, if a type is specified as A<I+J>::X<T>, I, J, and T are nondeduced. If a type is specified as void f(typename A<T>::B, A<T>), the T in A<T>::B is nondeduced but the T in A<T> is deduced. ]

like image 32
Kirill V. Lyadvinsky Avatar answered Sep 19 '22 08:09

Kirill V. Lyadvinsky