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 don't understand why the following code doesn't compile:
template< typename TypeArg >
class Data
{
public:
struct Selector1
{
};
template< typename Selector >
void foo()
{
}
};
template< typename TypeArg >
class Test
{
public:
void test();
};
template< typename TypeArg >
void Test< TypeArg >::test()
{
Data< TypeArg > data;
data.foo< typename Data< TypeArg >::Selector1 >();
}
I have tested it with GCC 4.6 and GCC 4.9. Both give me the same error:
test.cpp: In member function »void Test::test()«:
test.cpp:28:51: Error: expected »(« before »>« token
test.cpp:28:53: Error: expected primary-expression before »)« token
Can somebody tell me what needs to be done for the code to compile?
Since the type of data is dependent, the nature of data.foo is not known and needs to be disambiguated:
data.template foo<typename Data< TypeArg >::Selector1>();
// ^^^^^^^^
Related
This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 5 years ago.
I am trying to touch C++17 features and I have selected clang.
Here is simplified example of my code that could not be compiled via clang:
#include <iostream>
#include <limits>
template<
typename T,
template<typename T_> typename Final>
class Base
{
public:
decltype(auto) Foo() const noexcept
{
using TFinal = Final<T>;
auto& _this = static_cast<const TFinal&>(*this);
return _this.Bar<true>();
}
};
template<typename T>
class Derived :
public Base<T, ::Derived>
{
public:
template<bool min>
T Bar() const noexcept
{
return min ?
std::numeric_limits<T>::lowest() :
std::numeric_limits<T>::max();
}
};
int main()
{
Derived<int> instance;
auto result = instance.Foo();
std::cout << result << std::endl;
return 0;
}
It fails here:
return _this.Bar<true>();
and error message is:
main.cpp:14:32: error: expected expression
return _this.Bar<true>();
^
main.cpp:35:10: error: variable has incomplete type 'void'
auto result = instance.Foo();
^
Here is how I am compiling it:
clang++-5.0 main.cpp -std=c++17
Some additional info. Visual Studio 17 with latest language version can eat this. When bar function is not template, everything is ok...
Any suggestions what is wrong here?
Should be
return _this.template Bar<true>();
In your case _this has dependent type. To refer to its member templates you have to use the keyword template explicitly.
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 6 years ago.
The class foo contains a private tuple member. I want to get reference to an element of this tuple using a getElement<I>(). I came to this solution but it doesn't work when the object is passed to the constructor of another class bar:
#include <tuple>
template<class... Args>
class foo {
std::tuple<Args...> tup_;
public:
foo(Args... args) : tup_ {args...} {};
template<size_t I>
const typename std::tuple_element<I, std::tuple<Args...>>::type &
getElement() const {return std::get<I>(tup_);}
};
template<class T>
class bar;
template<class T, class U>
class bar<foo<T,U>> {
public:
bar(foo<T,U> f) {
auto j = f.getElement<0>(); // this is an ERROR!!! Line 22
}
};
int main()
{
foo<int, char> f(12,'c');
auto j = f.getElement<0>(); // but this is OK!
bar<decltype(f)> b(f);
return 0;
}
compiler output:
main.cpp: In constructor 'bar<foo<T, U> >::bar(foo<T, U>)':
main.cpp:22:33: error: expected primary-expression before ')' token
auto j = f.getElement<0>(); // this is an ERROR!!!
^
main.cpp: In instantiation of 'bar<foo<T, U> >::bar(foo<T, U>) [with T = int; U = char]':
main.cpp:32:24: required from here
main.cpp:22:29: error: invalid operands of types '<unresolved overloaded function type>' and 'int' to binary 'operator<'
auto j = f.getElement<0>(); // this is an ERROR!!!
You must warn the compiler that getElement is a template method. And to do it you must specify the template keyword, eg:
f.template getElement<0>()
This because otherwise the compiler tries to parse the code as f.getElement < 0 so that it tries to call the binary operator< on f.getElement and 0 which is not what you want to do.
This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 9 years ago.
In the example below, how do I find the address of the member function f
template<typename HANDLER>
void serialize(HANDLER &h) {
// Compiler error (gcc 4.8.1)
// test.cxx: In function ‘void serialize(HANDLER&)’:
// test.cxx:9:26: error: expected primary-expression before ‘int’
// auto x = &HANDLER::f<int>;
// ^
// test.cxx:9:26: error: expected ‘,’ or ‘;’ before ‘int’
auto x = &HANDLER::f<int>;
}
struct HandlerA {
template<typename T> void f() { }
};
struct HandlerB {
template<typename T> void f() { }
};
struct HandlerC {
template<typename T> void f() { }
};
int main() {
HandlerA a;
HandlerB b;
HandlerC c;
a.f<int>();
b.f<int>();
c.f<int>();
serialize(a);
serialize(b);
serialize(c);
}
You need to tell the compiler that f is a template so that it can parse the function correctly:
auto x = &HANDLER::template f<int>;
Casey is correct.
A template, before instantiation has no address. as the template is used (instantiated) with specific parameters, a unique function in memory is created.
You can use/create a real function with any type: int, char, float, double, classXYZ... there's no limit to how many pointers to that function there could be.
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.
Minmal working example:
#include <iostream>
struct Printer
{
template<class T>
static void print(T elem) {
std::cout << elem << std::endl;
}
};
template<class printer_t>
struct Main
{
template<class T>
void print(T elem) {
// In this case, the compiler could guess T from the context
// But in my case, assume that I need to specify T.
printer_t::print<T>(elem);
}
};
int main()
{
Main<Printer> m;
m.print(3);
m.print('x');
return 0;
}
My compiler (g++) gives me the error "expected primary-expression before ‘>’ token". What's wrong and how to fix it?
C++11 accepted.
clang gives a better error message in this case:
$ clang++ example.cpp -o example
example.cpp:18:20: error: use 'template' keyword to treat 'print' as a dependent template name
printer_t::print<T>(elem);
^
template
1 error generated.
Just add the template where it says to, and you're set.
I have some generic code which implements Pareto rule. It seems like well-formed code.
GCC 4.4 compiler messages about errors for newResult.set<Criterion>( criterion() ); expression. But I can't found problem.
Full error log:
trunk$ g++ -std=c++0x -o test test.cpp
t6.cpp: In member function ‘bool Pareto<Minimize<T>, Types ...>::operator()(Map&, Map&)’:
t6.cpp:24: error: expected primary-expression before ‘>’ token
t6.cpp:26: error: expected primary-expression before ‘>’ token
t6.cpp:26: error: expected primary-expression before ‘)’ token
t6.cpp:26: error: expected primary-expression before ‘>’ token
t6.cpp:26: error: expected primary-expression before ‘)’ token
t6.cpp: In member function ‘bool Pareto<Maximize<T>, Types ...>::operator()(Map&, Map&)’:
t6.cpp:43: error: expected primary-expression before ‘>’ token
t6.cpp:45: error: expected primary-expression before ‘>’ token
t6.cpp:45: error: expected primary-expression before ‘)’ token
t6.cpp:45: error: expected primary-expression before ‘>’ token
t6.cpp:45: error: expected primary-expression before ‘)’ token
Full code listing:
// TypeMap
template < typename ... Tail >
struct Holder;
template <typename ValueType, typename Head, typename ... Tail >
struct Holder<ValueType, Head, Tail ... > :
public Holder<ValueType, Head>,
public Holder<ValueType, Tail ... >
{};
template <typename ValueType, typename Head >
struct Holder<ValueType, Head>
{
ValueType value;
};
template < typename ... Types >
struct TypeMap;
template <typename ValueType, typename ... Types >
struct TypeMap<ValueType, Types ... > :
public Holder<ValueType, Types ... >
{
template <typename T>
void set(const ValueType& value)
{
((Holder<ValueType, T>*)this)->value = value;
}
template <typename T>
ValueType get()
{
return ((Holder<ValueType, T>*)this)->value;
}
};
// Objectives
template <typename Criterion> struct Maximize : public Criterion {};
template <typename Criterion> struct Minimize : public Criterion {};
// Criteria
struct Criterion1{ double operator()(){ return 0; }};
struct Criterion2{ double operator()(){ return 0; }};
// Pareto rule
template < typename ... Types > struct Pareto;
template < typename T, typename ... Types >
struct Pareto<Minimize<T>, Types ... >
{
template< typename Map >
bool operator()(Map& oldResult, Map& newResult)
{
typedef Minimize<T> Criterion;
Criterion criterion;
// ERROR HERE !!!
newResult.set<Criterion>( criterion() );
if(newResult.get<Criterion>() >= oldResult.get<Criterion>())
return false;
Pareto<Types ... > pareto;
return pareto(oldResult, newResult);
}
};
template < typename T, typename ... Types >
struct Pareto<Maximize<T>, Types ... >
{
template< typename Map >
bool operator()(Map& oldResult, Map& newResult)
{
typedef Maximize<T> Criterion;
Criterion criterion;
// ERROR HERE !!!
newResult.set<Criterion>( criterion() );
if(newResult.get<Criterion>() <= oldResult.get<Criterion>())
return false;
Pareto<Types ... > pareto;
return pareto(oldResult, newResult);
}
};
template<>
struct Pareto<>
{
template<typename Map>
bool operator()(Map& oldResult, Map& newResult)
{
oldResult = newResult;
return true;
}
};
int main()
{
TypeMap<double, Minimize<Criterion1>, Maximize<Criterion2>> oldResult, newResult;
Pareto<Minimize<Criterion1>, Maximize<Criterion2>> pareto;
pareto(oldResult, newResult);
}
Found it:
newResult.template set<Criterion>( criterion() );
if(newResult.template get<Criterion>() >= oldResult.template get<Criterion>())
return false;
You have to qualify the member function templates for the compiler in this case.
The lexer wouldn't be able to decide (at the time of template declaration, not instantiation) whether <Criterion means the start of a template parameter list or, instead, a comparison operator.
See
Using the template keyword as qualifier
What is the .template and ::template syntax about? (Comeau)
Standard, § 14.2, sub 4. and 5., noteworthy:
[ Note: As is the case with the typename prefix, the template prefix is allowed in cases where it is
not strictly necessary; i.e., when the nested-name-specifier or the expression on the left of the -> or . is not
dependent on a template-parameter, or the use does not appear in the scope of a template. —end note ]