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

柔情痞子 提交于 2019-12-11 01:29:16

问题


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 constexpr specifier, 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!