Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I need to specify the template argument type of a templated function here?

I have the following code:

template <typename T>
void f1( T t )
{
    std::cout << "f1( " << t << " ) called." << endl;
}

template <typename T>
void f2( T t )
{
    std::cout << "f2( " << t << " ) called." << endl;
}

template <typename F, typename T>
void call( F && f, T t )
{
    f( t );
}

template <typename T>
void foo( T t )
{
    call( f1<T>, t ); // Why is <T> necessary?
                      // f1(t) is a valid expression!
    call( f2<T>, t );
}

void bar()
{
    foo( 1 );
}

In the function foo() I need to specify the template argument, even though f1(t) is a valid expression. That's kinda destroying some possibilities in my code. My questions:

  1. Why do I need to specify the template argument?
  2. How can I work around that limitation? (C++11 or C++14 allowed).

(BTW: I'm currently using Visual Studio 2010 and I get the error C2896, if I leave the <T> out.)

like image 542
Ralph Tandetzky Avatar asked Jun 18 '13 12:06

Ralph Tandetzky


2 Answers

f1 is not a function, it's a template. You cannot pass a template as a function argument.

f1<T> is a function, so it can be passed.

like image 108
Angew is no longer proud of SO Avatar answered Oct 08 '22 17:10

Angew is no longer proud of SO


1. Why do I need to specify the template argument?

Well, f1 is not an object, but a function template. You can only pass objects to functions.

2. How can I work around that limitation? (C++11 or C++14 allowed).

Use an object with a templated operator(). Just replace the definition of f1() with

struct { template <typename T> void operator()( T t )
{
    std::cout << "f1( " << t << " ) called." << endl;
} } f1;

and likewise for f2(). In C++14 you can write it even nicer

static const auto f1 = []( auto t )
{
    std::cout << "f1( " << t << " ) called." << endl;
};
like image 34
Ralph Tandetzky Avatar answered Oct 08 '22 18:10

Ralph Tandetzky