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
Related
The following code
template<typename T>
void f();
template<typename T>
class A{
class B{
void f(){
f<T>();
}
};
};
does not compile, and gives the following error
<source>:10:15: error: expected primary-expression before '>' token
10 | f<T>();
What is the correct way to refer to T in the inner class?
Your problem is that f is not the name of a template on that line. It is the name of the method.
::f<T>(t);
Try that.
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:
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?.
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 a problem which seems to be already discussed here in:
CPP templated member function specialization
But the solution with this->template did not work with my example.
The following code fails with:
error: invalid operands of types '<unresolved overloaded function type>' and 'int'
to binary 'operator<'
with gcc 4.8.1
class Base { public: virtual int Do(){return 0;} };
class State1: public Base {};
class State2: public Base {};
template <typename ... T> class SM;
template <class StateBase, class HeadState, class ... States >
class SM<StateBase, HeadState, States...> : public SM< StateBase, States...>
{
protected:
HeadState headState;
template<int cnt> StateBase* GetNextState ( unsigned int index ) { return headState; }
};
template <class StateBase, class HeadState>
class SM< StateBase, HeadState>
{
protected:
HeadState headState;
template<int cnt> StateBase* GetNextState ( unsigned int index ) { return headState; }
};
template <class StateBase, class ... States >
class TopSM: public SM< StateBase, States...>
{
public:
void DoIt()
{
// following code fails with
// error: invalid operands of types '<unresolved overloaded function type>' and 'int' to binary 'operator<'
int nextState = this->template SM< StateBase, States...>::GetNextState <1>( 1 );
}
};
TopSM<Base, State1, State2> sm;
int main()
{
sm.DoIt();
return 0;
}
You need another template before GetNextState. If there are template arguments after an identifier and a ., ->, or :: before, and it's a member of something dependent on a template parameter, there needs to be a template keyword to disambiguate the less-than sign.
int nextState = this->template SM< StateBase, States...>::template GetNextState <1>( 1 );
Almost there, you need another template
int nextState = this->template SM< StateBase, States...>::template GetNextState <1>( 1 );
~~~~~~~~
The problem is that, because GetNextState comes from a template parameter, it doesn't know whether it's a static variable, function, template function or anything. The parser needs to continue, so it makes the assumption that its not a template function, so the < is parsed as a less-than operator, instead of the beginning of a template parameter list. From there, the parser gets confused and you get the error about invalid operands to >.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C++ passing a derived class shared_ptr to a templated function
The compiler has no problems with instantiation when we use pointers.
template <typename T> struct Base{
virtual ~Base() {}
};
template <typename T> struct Der: public Base<T> {
};
template <class T>
void f(Base<T>* b) {}
int main() {
Der<int> x;
f(&x);
}
However if I change f to use shared_ptrs, the compiler cannot find a match.
template <class T>
void f(shared_ptr<Base<T> >b) {}
int main() {
shared_ptr<Der<int> > x(new Der<int>);
f(x);
}
Z.cc: In function ‘int main()’:
Z.cc:45: error: no matching function for call to ‘f(std::tr1::shared_ptr<Der<int> >&)’
Changing x to
shared_ptr<Base<int> > x(new Der<int>);
will also work.
Why is there this difference in behavior?
shared_ptr<Der<int>> is not implicitly convertible to shared_ptr<Base<int>> whereas Der<int>* is implicitly convertible to Base<int>*. C++ doesn't automatically make types instantiated from a template convertible just because the template parameter types happen to be convertible, because that doesn't necessarily make sense and could be dangerous.
http://www2.research.att.com/~bs/bs_faq2.html#conversion