问题
Consider following example:
template <typename T>
void f (T t) {
std::cout << t << std::endl;
}
template <typename T>
struct F {
static constexpr void (*m) (T) = &f;
};
and usage:
F<int>::m (10);
So far, so good. Problem shows up when I want to store pointer to function template which takes for example an lambda expression. Consider this one:
template <typename T, typename C>
void g (T t, C c) {
std::cout << c (t) << std::endl;
}
template <typename T, typename C>
struct G {
static constexpr void (*m) (T, C) = &g;
};
and usage:
auto l = [] (auto v) { return v; };
G<int, decltype (l)>::m (20, l);
When compiling on GCC 5.3.1 with:
g++-5 -std=c++14 -Wall -Wextra -Wpedantic -Werror=return-type main.cpp -o main
I got:
‘constexpr void (* const G<int, main(int, char**)::<lambda(auto:1)> >::m)(int, main(int, char**)::<lambda(auto:1)>)’, declared using local type ‘main(int, char**)::<lambda(auto:1)>’, is used but never defined [-fpermissive]
Why this happens?
Is there any way I can achieve this code to work?
One possible solution that I am not interested in:
struct O {
template <typename T>
T operator() (T v) {
return v;
}
};
with usage:
G<int, O>::m (20, O {});
回答1:
The error, if you remove some stuff, says:
[...]
m[...] is used but never defined [-fpermissive]
So just follow the compiler's orders, and define it:
template <class T, class C>
constexpr void (*G<T,C>::m)(T,C);
And now it works. This is because in C++14, you are required to add a definition for static constexpr data members, from [class.static.data]:
The [static data] member shall still be defined in a namespace scope if it is odr-used ([basic.def.odr]) in the program and the namespace scope definition shall not contain an initializer.
This is no longer necessary in C++17 for constexpr static data members, as a result of p0386. The text now reads:
If the [static data] member is declared with the
constexprspecifier, it may be redeclared in namespace scope with no initializer (this usage is deprecated; see [depr.static_constexpr]).
来源:https://stackoverflow.com/questions/44739864/how-to-store-pointer-to-function-template-which-takes-callable-object-as-one-of