如何存储指向以可调用对象为参数之一的函数模板的指针 [英] How to store pointer to function template which takes Callable object as one of its parameters
问题描述
考虑以下示例:
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表达式的函数模板的指针时,出现问题。考虑以下一个:
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;
};
和用法:
auto l = [] (auto v) { return v; };
G<int, decltype (l)>::m (20, l);
在GCC 5.3.1上使用以下命令进行编译时:
When compiling on GCC 5.3.1 with:
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]
为什么会这样?
有什么方法可以使我的代码正常工作吗?
一种我不感兴趣的解决方案:
One possible solution that I am not interested in:
struct O {
template <typename T>
T operator() (T v) {
return v;
}
};
用法:
G<int, O>::m (20, O {});
推荐答案
如果删除某些内容,该错误将显示:
The error, if you remove some stuff, says:
[...]
m
[...]已使用但从未使用定义的[-fpermissive]
[...]
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);
现在它可以工作了。这是因为在C ++ 14中,您需要从 [class.static.data] :
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]:
[static data]成员应如果在程序中被使用([basic.def.odr]),并且仍然在命名空间范围中定义它,并且该命名空间范围定义不应包含初始化程序。
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.
对于C ++ 17中的 constexpr
静态数据成员,这不再是必需的,作为 p0386 的结果。文本现在读取:
This is no longer necessary in C++17 for constexpr
static data members, as a result of p0386. The text now reads:
如果使用
constexpr
说明符声明了[静态数据]成员,则可能在没有初始化程序的命名空间范围内重新声明(不建议使用此用法;请参见[depr.static_constexpr])。
If the [static data] member is declared with the
constexpr
specifier, it may be redeclared in namespace scope with no initializer (this usage is deprecated; see [depr.static_constexpr]).
这篇关于如何存储指向以可调用对象为参数之一的函数模板的指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!