This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 8 years ago.
To put it somewhat vaguely, from the snippet (tt.cc) below it seems to me as if the template template notion lacked some kind of a "transparency". While I don't seem to fathom what other template argument should A::f() be provided (besides the template template one), I might as well be just missing some banality here.
template <class T>
class A {
public:
template< template<class> class U >
void f( int i ) {
// ...
}
};
template< class T, template<class> class U >
class B {
public:
void f( int i ) {
A<T> a;
a.f<U>( i );
}
};
int main() {
return 0;
}
The error message it provides is:
g++ ./tt.cc -o tt
./tt.cc: In member function ‘void B<T, U>::f(int)’:
./tt.cc:17:10: error: missing template arguments before ‘>’ token
a.f<U>( i );
^
Compilation exited abnormally with code 1
Any ideas greatly appreciated.
What you are seeing is the compiler interpreting the > token inside f<U> as the inequality operator. You need to add .template to let the compiler know you mean a template argument.
void f( int i ) {
A<T> a;
a.template f<U>( i );
}
Live Example.
See also Where and why do I have to put the “template” and “typename” keywords?.
Related
This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 2 years ago.
I would like to use a static method in a template parameter in my function in an enable_if expression. However, the static method is also a template, and I get compiler errors.
The error message:
$ g++ test.cpp
test.cpp:20:36: error: invalid declarator before ‘(’ token
20 | std::enable_if_t<A::method_a<param>()>
Code sample:
#include <type_traits>
struct B
{
template<int param>
static constexpr int method_a()
{
return param == 5;
}
static constexpr int method_b(int param)
{
return param == 5;
}
};
// this doesn't work
template<int param, typename A>
std::enable_if_t<A::method_a<param>()>
func_a(A& a)
{}
// this works
template<int param, typename A>
std::enable_if_t<A::method_b(param)>
func_b(A& a)
{}
int main()
{
B b;
func_b<5>(b); // this doesn't work
func_a<5>(b); // this works
return 0;
}
In func_a, the name method_a is a dependent name i.e. the meaning of method_a depends on the template type parameter A. If the name is a member template, you need to specify that with the template keyword:
template<int param, typename A>
std::enable_if_t<A::template method_a<param>()>
// ^^^^^^^^
func_a(A& a){}
Here's a demo.
This question already has answers here:
"invalid use of incomplete type" error with partial template specialization
(5 answers)
Template specialization of particular members?
(2 answers)
Closed 3 years ago.
Why am I getting this error in the following:
template<typename T,typename Y>
class MyContainer
{
std::vector<T> list;
public:
void append( T&& elem) ;
};
template<typename T>
void MyContainer<T,int>::append(T&& elem)
{
list.push_back(elem);
}
int main()
{
}
error: invalid use of incomplete type ‘class >MyContainer’
void MyContainer::append(T&& elem)
I initially thought that, what if someone passed a second template parameter as double, it won't work, so I need to provide a non specialized member function definition first and may be on top of that I can provide partial specialization.
But even after adding the below I still get the same error:
template<typename T, typename Y>
void MyContainer<T,Y>::append(T&& elem)
{
list.push_back(elem);
}
This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 6 years ago.
Compiler: TDM-GCC 5.1.0 (SJLJ Unwinding)
I'm having an issue passing variable number of type arguments to a static variadic template method call inside of a template function. I've tried every syntax variation, but it won't compile, so I can only assume I'm doing this wrong.
Here's the setup:
#include <iostream>
template <class T>
struct Foo
{
template <class...>
static void test()
{
std::cout << "Foo<T>::test<...>() called.";
}
};
template <class T, class... Args>
void bar()
{
Foo<T>::test<Args...>(); //error happens here
}
int main()
{
bar<int, int>();
}
This gives the compiler error: expected primary-expression before '...' token.
I thought pack expansions looked like Args..., but that doesn't seems to work here.
Any help is appreciated.
You need to tell the parser that dependant test is a template:
template <class T, class... Args>
void bar()
{
Foo<T>::template test<Args...>(); //error happens here
^^^^^^^^^
}
demo
This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 7 years ago.
I have the following code:
template <typename T>
struct Data {
struct Embed
{
T t;
};
};
struct Functor {
template <typename T>
void foo( typename Data<T>::Embed & e) {}
};
template <typename T, typename F>
struct Caller
{
F f;
template <typename T>
void invoke() {
typename Data<T>::Embed e;
f.foo<T>(e); //compiler error pointed this line
}
};
Then I specialized the template as:
Caller<int, Functor> c;
c.invoke();
compiler error is : error: expected primary-expression before '>' in f.foo<T>(e); line. It seems compiler suddenly doesn't know what T is even it is specified in the template declaration on the function.
Take out the explicit specified T in foo.invoke(e) line will result could not deduce template parameter 'T'
How do I fix this? (I still want to keep the functionality that Caller can have generic functor and functor's function can be templated).
You are using:
template <typename T>
void invoke() {
typename Data<T>::Embed e;
f.foo<T>(e); //compiler error pointed this line
}
inside Caller even though T is one of the parameters of Caller. Remove the line
template <typename T>
and use just:
void invoke() {
typename Data<T>::Embed e;
// f.foo<T>(e); //compiler error pointed this line
f.template foo<T>(e); // Need the template keyword here.
}
However, as #Nawaz pointed out in a comment, that changes the semantics of invoke. If T in invoke was meant to be different than the T used to instantiate Caller, then it will be better to use a different name, say U.
The problem is that f is of type F which is template parameter, f.foo is a dependent name and which happens to be a function template. So you've to use template in a very weird way:
f.template foo<T>(e);
For further explantion, see these:
short explanation
long explanation
Also, I'd advise you to use U as template parameter for the function template invoke if at all it needs to be a template, else you can make it a normal function (i.e if the T of invoke is ought to be same as T of the enclosing class template).
Hope that helps.
This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 8 years ago.
I have to following example code. In this code I have two template classes each with a template function. One of the classes has an object of the other class and in the template function it calls the template of the other class.
template<typename T>
class A{
public:
A(T a): a(a){}
template< typename V> V foo(){
return this->a;
}
private:
T a;
};
template<typename T>
class B{
public:
B( A<T> a): a(a){}
template<typename V>V foo2(){
return this->a.foo<V>();
}
private:
A<T> a;
};
int
main()
{
A<int> a(5);
double aTest = a.foo<double>();
B<int> b(a);
double c = b.foo2< double >();
}
I need to provide the template element after the function call, because automatic type deduction does not work for functions, were only the return type depends on the template parameter. This works for aTest. But when I add the next two lines I get the following compiler error:
build/main.cpp: In member function 'V B<T>::foo2()':
build/main.cpp:32:23: error: expected primary-expression before '>' token
return this->a.foo<V>();
^
build/main.cpp:32:25: error: expected primary-expression before ')' token
return this->a.foo<V>();
You need to use:
template<typename V>V foo2(){
return this->a.template foo<V>();
}
To find gory details of why you need to use template in the call to a.foo, please take a look at this SO answer: https://stackoverflow.com/a/613132/434551