考虑以下示例:
template <typename T>
void f (T t) {
std::cout << t << std::endl;
}
template <typename T>
struct F {
static constexpr void (*m) (T) = &f;
};
和用法:
F<int>::m (10);
到现在为止还挺好。当我想存储指向带有lambda表达式的函数模板的指针时,出现问题。考虑一下这一点:
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;
};
和用法:
auto l = [] (auto v) { return v; };
G<int, decltype (l)>::m (20, l);
在GCC 5.3.1上使用以下命令进行编译时:
g++-5 -std=c++14 -Wall -Wextra -Wpedantic -Werror=return-type main.cpp -o main
我有:
‘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]
为什么会这样?
有什么方法可以使此代码起作用?
我不感兴趣的一种可能的解决方案:
struct O {
template <typename T>
T operator() (T v) {
return v;
}
};
用法:
G<int, O>::m (20, O {});
最佳答案
如果删除某些内容,该错误将显示:
因此,只需遵循编译器的命令并对其进行定义:
template <class T, class C>
constexpr void (*G<T,C>::m)(T,C);
现在就可以了。这是因为在C++ 14中,您需要从[class.static.data]添加静态constexpr数据成员的定义:
由于p0386,对于
constexpr
静态数据成员,在C++ 17中不再需要此方法。文字now reads: