HC4*_*ica 3 c++ decltype template-specialization c++11
我尝试在模板类中使用 decltype,如下所示:
#include <functional>
template <typename T>
class A
{
typedef decltype(std::bind(&A::f, std::declval<A>())) some_type;
void f();
};
Run Code Online (Sandbox Code Playgroud)
效果很好,但现在我想添加一个明确的专业化:
template <>
class A<void>
{
typedef decltype(std::bind(&A::f, std::declval<A>())) some_type;
void f();
};
Run Code Online (Sandbox Code Playgroud)
这次g++报错:
test.cpp:14:33: error: incomplete type 'A<void>' used in nested name specifier
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?我正在使用海湾合作委员会4.5。
编辑:如果我将声明移到void f();typedef 之上,按照 Johannes 的建议,我会得到(略有)不同的错误:
test.cpp:15:62: error: invalid use of incomplete type 'class A<void>'
test.cpp:13:1: error: declaration of 'class A<void>'
test.cpp:15:62: error: initializing argument 2 of 'std::_Bind<typename std::_Maybe_wrap_member_pointer<_Tp>::type(_ArgTypes ...)> std::bind(_Functor, _ArgTypes ...) [with _Functor = void (A<void>::*)(), _ArgTypes = {A<void>}, typename std::_Maybe_wrap_member_pointer<_Tp>::type = std::_Mem_fn<void (A<void>::*)()>]'
test.cpp:15:62: error: invalid use of incomplete type 'class A<void>'
test.cpp:13:1: error: declaration of 'class A<void>'
test.cpp:15:62: error: initializing argument 2 of 'std::_Bind<typename std::_Maybe_wrap_member_pointer<_Tp>::type(_ArgTypes ...)> std::bind(_Functor, _ArgTypes ...) [with _Functor = void (A<void>::*)(), _ArgTypes = {A<void>}, typename std::_Maybe_wrap_member_pointer<_Tp>::type = std::_Mem_fn<void (A<void>::*)()>]'
Run Code Online (Sandbox Code Playgroud)
你的订单是错误的。尝试交换一下
template <>
class A<void>
{
void f();
typedef decltype(std::bind(&A::f, std::declval<A>())) some_type;
};
Run Code Online (Sandbox Code Playgroud)
在主模板中,名称A::f是相关的,编译器将查找延迟到声明的点f(A::f在 C++0x 中不再真正依赖,因为A引用当前实例化,因此f引用当前实例化的成员,但作为当前规范中存在一个漏洞(它与依赖基类有关),但编译器延迟了查找)。在显式专业化中,名称不相关,并且立即完成查找,这就是您需要f在引用它之前声明的原因。
编辑:您错误地使用了std::bind. 您给出的第二个参数的类型为A<void>,它将被复制/移动std::bind到其创建的调用包装对象中。这需要一个完整的类型A<void>。
如果您只想传递A调用成员函数的引用,则可以传递 a declval<A*>(),该std::bind机制同样将其检测为成员指针调用的神奇第一个参数。
但在我看来,你想调查一下std::function<>,而不是这样做std::bind和decltype搞乱。毕竟,您拥有一个强大的工具集,但是通过使用这个可疑的decltype表达式,您抛弃了标准库为您提供的所有通用性,并限制自己只能使用该单个std::bind表达式。那可不好。