C++ parameter pack usage [duplicate] - c++

This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 1 year ago.
I want to encapsulate a class which uses template parameter pack and function template into another similar class, like the following example:
#include <iostream>
template<typename ... Args>
struct O2 {
template<int T>
void f() {
}
};
template<typename ... Args>
struct O1 {
O2<Args...> i2;
template<int T>
void g() {
i2.f<T>();
}
};
int main()
{
O1<int> i1;
i1.g<1>();
return 0;
}
but the compliler it says I'm wrong:
main.cpp: In member function 'void O1<Args>::g()':
main.cpp:18:17: error: expected primary-expression before ')' token
18 | i2.f<T>();
| ^
main.cpp: In instantiation of 'void O1<Args>::g() [with int T = 1; Args = {int}]':
main.cpp:25:12: required from here
main.cpp:18:13: error: invalid operands of types '<unresolved overloaded function type>' and 'int' to binary 'operator<'
18 | i2.f<T>();
| ~~~~^~
I can't modify the inner class (O2), and I can't use inheritance. Any idea how to do it?
Thx

The correct syntax is:
i2.template f<T>();

Related

calling a template method results in no match for 'operator<' [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 a problem with the following Minimal Example:
enum class modes_t {m1=0u, m2=1u};
class A {
public:
static inline A& get(void) noexcept{
static A inst;
return inst;
}
template<modes_t mode>
inline void start(void) noexcept {}
};
template<typename T>
class B {
public:
static inline void start(void) noexcept {
T::get().start<modes_t::m1>();
}
};
int main() {
B<A>::start();
}
If I compile it with g++ v.7.3, (with -std=c++17 and also with -std=c++14) I get the following errors:
main.cpp: In static member function ‘static void B<T>::start()’:
main.cpp:17:37: error: expected primary-expression before ‘)’ token
T::get().start<modes_t::m1>();
^
main.cpp: In instantiation of ‘static void B<T>::start() [with T = A]’:
main.cpp:22:11: required from here
main.cpp:17:23: error: no match for ‘operator<’ (operand types are ‘<unresolved overloaded function type>’ and ‘modes_t’)
T::get().start<modes_t::m1>();
So the compiler thinks, that the line T::get().start<modes_t::m1>(); is a less then comparison of T::get().start and modes_t::m1.
What should I do, to tell the compiler, that this expression should call start() in class A?
You need to add template keyword to tell the compiler that start is a member function template. e.g.
T::get().template start<modes_t::m1>();
// ~~~~~~~~
BTW: You can't specify modes_t::m1 as the template argument; start expects an int as its template parameter and there are no implicit conversions from the values of a scoped enumerator to integral types.

Access to private tuple element through a template member function [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 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.

Error when calling an Integral template member function with g++ and clang++ [duplicate]

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'm currently stuck on a compilation error, which I can't really identify...
Here's a minimal working example:
#include <iostream>
template <typename T, int R>
class a_type
{
public:
template <int N>
double segment()
{
return 42;
}
};
template <int M>
double func()
{
a_type<double, M> a;
return a.segment<1>();
}
int main(int argc, char *argv[])
{
std::cout << func<10>() << std::endl;
return 0;
}
The error message from GCC reads:
g++ main.cpp -o main
main.cpp: In function 'double func()':
main.cpp:18:26: error: expected primary-expression before ')' token
return a.segment<1>();
^
main.cpp: In instantiation of 'double func() [with int M = 10]':
main.cpp:23:28: required from here
main.cpp:18:22: error: invalid operands of types '<unresolved overloaded function type>' and 'int' to binary 'operator<'
return a.segment<1>();
^
Clang also says something similar:
clang++ main.cpp -o main
main.cpp:18:26: error: expected expression
return a.segment<1>();
^
So based on GCC's error message, 'a.segment' is a member function call missing the parentheses, which obviously gets rejected. But that does not make sense at all, since I don't see any reason for treating that expression as such.
Moreover, if I change M to any integral number on line 17, like so:
#include <iostream>
template <typename T, int R>
class a_type
{
public:
template <int N>
double segment()
{
return 42;
}
};
template <int M>
double func()
{
a_type<double, 58> a;
return a.segment<1>();
}
int main(int argc, char *argv[])
{
std::cout << func<10>() << std::endl;
return 0;
}
then the code compiles and produces the expected result.
I would be very happy if somebody could enlighten me and show me what I am missing here.
The compiler doesn't know that a.segment is a template (it might depend on the value of M). So you have to tell it:
return a.template segment<1>();
In your second example it knows everything about the type of a, and so there is no problem.
The compiler tells you that it has problems with
a_type<double, M> a;
return a.segment<1>();
because it cannot tell what members a can have, as it is a template (that might be specialized for some values of M).
main.cpp:18:22: error: invalid operands of types '<unresolved overloaded function type>' and 'int' to binary 'operator<'
return a.segment<1>();
^
If segment is a template, it would be treated as segment<1>. If segment is a member variable of a, it should be compiled as a.segment < 1. How is the compiler to know?
You can fix this by using
return a.template segment<1>();

why this piece code(some template stuff) compiled well in msvc10 but compiled failed in gcc4.8.1? [duplicate]

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.
#include <iostream>
#include <typeinfo>
using namespace std;
struct mystruct{};
template<typename T>
struct map;
//specification
#define MAPPING(Key, Val) \
template<> \
struct map<Key> \
{ \
typedef Val mapping_type; \
};
MAPPING(mystruct, int)
template<typename T>
void func(T t)
{
map<T>::mapping_type i = 999;
cout<<i<<endl;
}
int main() {
// your code goes here
mystruct ms;
func(ms);
return 0;
}
I try to do some type mapping(here mapping mystruct to int) via specification, but it can't compiled by gcc4.8.1, help!
or what is the right way to accomplish this, thanks!
http://ideone.com/yefbtk
Here are the error messages:
prog.cpp: In function ‘void func(T)’:
prog.cpp:23:2: error: need ‘typename’ before ‘map<T>::mapping_type’ because ‘map<T>’ is a dependent scope
map<T>::mapping_type i = 999;
^
prog.cpp:23:23: error: expected ‘;’ before ‘i’
map<T>::mapping_type i = 999;
^
prog.cpp:24:8: error: ‘i’ was not declared in this scope
cout<<i<<endl;
^
prog.cpp: In instantiation of ‘void func(T) [with T = mystruct]’:
prog.cpp:31:9: required from here
prog.cpp:23:2: error: dependent-name ‘map<T>::mapping_type’ is parsed as a non-type, but instantiation yields a type
map<T>::mapping_type i = 999;
^
prog.cpp:23:2: note: say ‘typename map<T>::mapping_type’ if a type is meant
As Mat pointed out in the comments, you must include typename before using map::mapping_type.
template<typename T>
void func(T t)
{
typename map<T>::mapping_type i = 999;
cout<<i<<endl;
}

Address of templated member function [duplicate]

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.