将函数 f 传递给以 f 的类型模板化的 class 的构造函数

Passing a function f to the contructor of a class templated on the type of f

我正在探索两种将函数传递给class模板Bar的构造函数的不同方法,如下所示和online.

测试的编译器:GCC 5.4.0 和 clang 3.8.0。 (在线版本中禁用了有问题的结构。)

#include <iostream>
#include <cxxabi.h>

#define DEMANGLE( object )                                                          \
{                                                                                   \
    int status;                                                                     \
    char* name = abi::__cxa_demangle( typeid( object ).name() , 0 , 0 , &status );  \
    if( !status ) std::cout << name << std::endl;                                   \
    delete name;                                                                    \
} 

template<typename T> 
struct Bar;

template<typename ...Args> 
struct Bar<void(Args...)>
{
#if 0
    Bar( void(Args...) )        // OKAY 
    {                           // Question 1: need to assign a name to the function void(Args...)
    }
#else
    Bar( void(Args...) func )   // ERROR
    {
    }
#endif    
};

void wiggle( bool , short , int )
{   
}

template<typename F>
void wrapper( F f )
{
    //DEMANGLE( f )             // optional print out of the type of F
    Bar<F> bar( f ) ;           // Question 2: incomplete type error -- why is specialization of Bar not chosen???
}

int main()
{
    wrapper( wiggle );
    Bar<decltype(wiggle)> f( &wiggle );
}

问题一

我第一次尝试将函数wiggle传递给Bar是直接实例化后者如下Bar<decltype(wiggle)> f( &wiggle )。问题是如何将name/reference 的函数传递给Bar::Bar(f) 的构造函数。使用未命名参数 Bar( void(Args...) ) 编写 ctor 可以编译,但是当我尝试命名或引用传递给 ctor 的参数时,就像这样 Bar( void(Args...) func ),我得到一个编译器错误

source_file.cpp:23:21: error: expected ')'
        Bar( void(Args...) func )       // ERROR
                           ^
source_file.cpp:23:5: note: to match this '('
        Bar( void(Args...) func )       // ERROR

问题二

我第二次尝试将函数传递给 Bar 使用函数 void wrapper( F f ) 来调用 Bar<F> bar( f )。奇怪的是,两个编译器都使用 Bar 的(未实现的)基本模板而不是生成错误

的特化
source_file.cpp:37:9: error: implicit instantiation of undefined template 'Bar<void (*)(bool, short, int)>'
        Bar<F> bar( f );
               ^
source_file.cpp:42:2: note: in instantiation of function template specialization 'wrapper<void (*)(bool, short, int)>' requested here
        wrapper( wiggle );
        ^
source_file.cpp:13:8: note: template is declared here
struct Bar;

特别令人困惑的是类型名称信息转储宏 DEMANGLE 确认传递给 wrapperF 的类型是 void (*)(bool, short, int).

问题是wiggle传递给wrapper时隐式转换为函数指针,所以F的实际类型是:

void (*)(bool, short, int)

...无法匹配 void(Args)。你可以使用 std::remove_pointer_t:

Bar<std::remove_pointer_t<F>> bar( f );

关于你的第一个错误,Bar(void (Args...) func) 不是一个正确的构造,Bar(void func(Args...)) 应该在这里,但是 that would be equivalent to:

Bar(void (*func)(Args...))

...这更清楚(在我看来)。