繁体   English   中英

如何存储指向以可调用对象为参数之一的函数模板的指针

[英]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表达式的函数模板的指针时,出现问题。 考虑一下这一点:

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中不再需要此方法。 文本现在显示为

如果[constant data]成员是用constexpr说明符声明的,则可以在没有初始化程序的命名空间范围内重新声明它(不建议使用此用法;请参见[depr.static_constexpr])。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM