Address of templated member function [duplicate] - templates

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.

Related

C++ parameter pack usage [duplicate]

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>();

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.

clang error while compiling template [duplicate]

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?

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.

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;
}