将函数f传递给在f类型上模板化的类的构造函数

时间:2018-02-02 14:55:26

标签: c++ templates specialization variadic

我正在探索两种方法将函数传递给类模板Bar的ctor,如下所示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 );
}

问题1

我首次尝试将函数wiggle传递给Bar是直接将后者实例化为Bar<decltype(wiggle)> f( &wiggle )。问题是如何命名/引用传递给构造函数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

问题2

我第二次尝试将函数传递给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确认传递给F的{​​{1}}类型为wrapper

1 个答案:

答案 0 :(得分:2)

问题是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...))

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