Referencing a template from an inner class [duplicate] - c++

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 have the following code
template<typename VP,bool b>
class ValueProcessor{
template<typename Access,typename X> void processValue(X& x){}
};
template<typename VP>
class ValueProcessor<VP,true>{
public:
template<typename Access,typename X> void processValue(X& x);
};
template<typename VP>
template<typename Access,typename X>
void ValueProcessor<VP,true>::processValue(X& x){
class Updater{
ValueProcessor<VP,false> valPro;
X x;
public:
void operator()(){
valPro.processValue<Access,X>(x);
};
};
}
but it fails with this error
source>: In member function 'void ValueProcessor<VP, true>::processValue(X&)::Updater::operator()()':
<source>:23:32: error: expected primary-expression before ',' token
23 | valPro.processValue<Access,X>(x);
|
^
How can I refer to Access from the inner class?

As pointed out in the comment the solution is to add a .template discrimitaor before the member function name:
valPro.template processValue<Access,X>(x);
This is necessary because the type of ValueProcessor<VP,false> valPro is a dependent type (i.e. it's actual type depends on the type of the template parameter VP) the c++ language requires to add the .template disambiguator if you want to call a template member function of VP. Otherwise the parser would interpret the opening < as less-than operator.
See cppreference for a more in-depth discussion. The template disambiguator is described at the very end of that article.

Related

Nested class in templated class used in templated function syntax error [duplicate]

This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 3 years ago.
Suppose I have the following:
template<typename T>
struct Foo
{
public:
class Bar
{
};
};
If I then define the function
template <typename T>
void func(Foo<T>::Bar g) { }
I get an error:
syntax error: identifier 'Bar'
Why do I get the error and how can I solve it so that I can use the templated function.
Use
template <typename T>
void func( typename Foo<T>::Bar g ) { }
Otherwise the construction Foo<T>::Bar is not considered by the compiler as a type specifier but as an expression.

Pass class with templated method as template parameter with GCC [duplicate]

This question already has answers here:
C++ template compilation error: expected primary-expression before ‘>’ token [duplicate]
(1 answer)
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 4 years ago.
Is it possible to pass object of a class with templated method as a template parameter under GCC? All search I conducted pointed me to questions regarding templated class, which is not applicable in my case.
Sample code:
#include <iostream>
class Foo
{
public:
template<typename T>
void print(const T& arg) const
{
std::cout << arg << std::endl;
}
};
template<typename A>
void print(const A& printer)
{
printer.print<int>(1);
}
int main()
{
Foo foo;
print<Foo>(foo);
return 0;
}
Compiling under MinGW.org GCC-6.3.0-1 I get the following results:
tmpl.cpp: In function 'void print(const A&)':
tmpl.cpp:16:19: error: expected primary-expression before 'int'
printer.print<int>(1);
^~~
tmpl.cpp:16:19: error: expected ';' before 'int'
VisualStudio compiles the same code cleanly, application works as expected. If I make print function not templated, so that is explicitly takes object of Foo it works as expected both compilers.
You need to use template keyword to tell that print is a template.
Inside a template definition, template can be used to declare that a dependent name is a template.
e.g.
template<typename A>
void print(const A& printer)
{
printer.template print<int>(1);
// ~~~~~~~~
}
print is a dependent name, it depends on the template parameter A. Before the template gets instantiated the compiler knows nothing about A; so you need to add the template keyword to tell the compiler that print is a template, then the < after the name print is valid; otherwise < will be treated as the operator< then cause the error.
You need the template keyword in order to specify that print() is a template, like this:
printer.template print<int>(1);

Return a struct declared inside template class from a template method [duplicate]

This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 4 years ago.
I have the following:
#include <vector>
template <class T>
class A
{
public:
struct S
{
int a;
};
std::vector<S> returnStructs(void);
};
template <class T>
std::vector<A<T>::S> A<T>::returnStructs(void)
{
}
int main(void)
{
}
but when I try to compile I get:
error: template argument for template type parameter must be a type; did you forget
'typename'?
std::vector<A<T>::S> A<T>::returnStructs(void)
^
typename
so I switched out that line for:
std::vector<A<int>::S> A<T>::returnStructs(void)
^
'int' instead of 'T'
but then I get a new compiler error:
error: return type of out-of-line definition of 'A::returnStructs' differs from that in the
declaration
std::vector<A<int>::S> A<T>::returnStructs(void)
~~~~~~~~~~~~~~~~~~~~~~ ^
so any thoughts on how to fix this?
Also I realize I can just take struct S out of class A and be done with all these issues but I still feel like it should be possible to solve this without changing class A.
The first compiler error told you exactly what was wrong: did you forget 'typename'
As S is a member of a template you need to add typename to tell the compiler that it should delay the lookup of the name until after the template is resolved:
template <class T>
std::vector<typename A<T>::S> A<T>::returnStructs(void)

Template function requires existence of inner class in non-templated class [duplicate]

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.
There's a template function f that requires its template parameter type T to have an inner class named Inner.
Inside f the class T::Inner shall be instantiated.
First try.
//
// "error: need 'typename' before 'T:: Inner' because 'T' is a dependent scope"
//
template <typename T>
void f( void )
{
T::Inner i;
}
I get that, so here comes the second try, where I don't get what's wrong:
/// "error: expected ';' before 'i'
template<typename T>
void f ( void )
{
typename T::Inner I;
I i;
}
Why is that?
In my understanding:
Inner is declared as type.
The template has not yet been instantiated.
Whether the type Inner exists or not first becomes relevant
on instantiation - not definition. Where am I going wrong?
I think you want to do
typename T::Inner i;
or
typedef typename T::Inner I;
I i;
whereas what you have in the question actually declares I to be a variable, and then right after that you are trying to use it as though it's a type.

What does the error "expected primary-expression before '>' token" mean in this context? [duplicate]

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.
The following code (also on ideone):
// A type templated for different function call signatures.
template <typename Signature> class Used;
template <typename T_Ret, typename ...T_Args>
class Used<T_Ret(T_Args...)> {
public:
// A static method for a specific type.
template <typename T>
static void specific() { }
};
// Some class using the above.
template <typename T>
class User {
public:
// A method that must call the specific function of used.
template <typename T_Ret, typename ...T_Args>
void method() {
using It = Used<T_Ret(T_Args...)>;
using Me = T;
// error: expected primary-expression before '>' token
It::specific<Me>();
}
};
int main() {
User<int> user;
user.method<void, int>();
}
gives the following error (at least using GCC):
test.cpp: In member function 'void User<T>::method()':
test.cpp:20:18: error: expected primary-expression before '>' token
It::specific<Me>();
^
And I have no idea why... The error does not occur if the template parameters are removed from the Used class.
Am I doing something wrong (i.e., missing a template or typename keyword somewhere)? Is this a bug in GCC? Is there a workaround?
Because specific is a dependent name you need a template keyword:
It::template specific<Me>();
//--^^^^^^^^