将函数 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
确认传递给 wrapper
的 F
的类型是 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...))
...这更清楚(在我看来)。
我正在探索两种将函数传递给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
确认传递给 wrapper
的 F
的类型是 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...))
...这更清楚(在我看来)。