如何存储指针以功能模板,该模板将可呼叫对象作为其参数之一

How to store pointer to function template which takes Callable object as one of its parameters

本文关键字:对象 呼叫 参数 存储 何存储 指针 功能      更新时间:2023-10-16

考虑以下示例:

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

错误,如果您删除了一些东西,请说:

[...] m [...]被使用,但从未定义[-fpermissive]

因此,只需按照编译器的订单来定义:

template <class T, class C>
constexpr void (*G<T,C>::m)(T,C);

现在起作用。这是因为在C 14中,您需要从[class.static.data]添加静态constexpr数据成员的定义:

如果程序空间范围([basic.def.odr](和命名空间范围定义不包含初始化程序,则[静态数据]成员仍应在命名空间范围中定义。

。 。

由于P0386的结果,constexpr静态数据成员的C 17不再需要。文本现在读取:

如果[静态数据]成员是用constexpr指定符声明的,则可以是在命名空间范围内重新编辑而没有初始化器(此用法已弃用;请参见[DEPRE.STATIC_CONSTEXPR]。/blockquote>