简体   繁体   English

类模板特化中的decltype

[英]decltype in class template specialization

I am trying to use decltype inside a template class as follows: 我试图在模板类中使用decltype,如下所示:

#include <functional>
template <typename T>
class A
{
    typedef decltype(std::bind(&A::f, std::declval<A>())) some_type;

    void f();
};

That works fine, but now I'd like to add an explicit specialization: 这很好,但现在我想添加一个明确的专业化:

template <>
class A<void>
{
    typedef decltype(std::bind(&A::f, std::declval<A>())) some_type;

    void f();
};

This time g++ gives an error: 这次g ++给出了一个错误:

test.cpp:14:33: error: incomplete type 'A<void>' used in nested name specifier

What am I doing wrong? 我究竟做错了什么? I am using gcc 4.5. 我正在使用gcc 4.5。

EDIT: If I move the declaration of void f(); 编辑:如果我移动void f();的声明void f(); to above the typedef, as suggested by Johannes, I get (slightly) different errors: 如Johannes所建议的那样,在typedef之上,我得到(稍微)不同的错误:

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>::*)()>]'

Your order is wrong. 你的订单错了。 Try exchanging it 尝试交换它

template <>
class A<void>
{    
    void f();
    typedef decltype(std::bind(&A::f, std::declval<A>())) some_type;
};

In the primary template, the name A::f was dependent and the compiler delayed lookup to a point where f was declared ( A::f is not really dependent in C++0x anymore, since A refers to the current instantiation and therefor f to a member of the current instantiation, but as there is a loophole in the current specification (it has to do with dependent base classes), the compiler delayed the lookup nontheless). 在主模板中,名称A::f是依赖的,并且编译器将查找延迟到声明f的点( A::f实际上不再依赖于C ++ 0x,因为A指的是当前实例化,因此f到当前实例化的成员,但由于当前规范中存在漏洞(它与依赖的基类有关),编译器仍延迟了查找)。 In the explicit specialization, the name is not dependent and lookup is done immediately, which is the reason you need to declare f before referring to it. 在显式特化中,名称不依赖,并且立即执行查找,这是您在引用它之前需要声明f的原因。

Edit: You are wrongly using std::bind . 编辑:您错误地使用std::bind The second argument you give is of type A<void> , which will be copied/moved by std::bind into its created call wrapper object. 您给出的第二个参数是类型A<void> ,它将被std::bind复制/移动到其创建的调用包装器对象中。 This requires a complete type A<void> . 这需要一个完整的类型A<void>

If you want to merely pass a reference to A on which the member function is called, you can pass a declval<A*>() , which the std::bind mechanism equally detects as magical first argument to a member pointer invocation. 如果您只想传递对其中调用成员函数的A的引用,则可以传递一个declval<A*>()std::bind机制同样将其视为成员指针调用的神奇第一个参数。

But it seems to me you want to look into std::function<> , instead of doing this std::bind and decltype mess. 但在我看来,你想要研究std::function<> ,而不是做这个std::binddecltype混乱。 After all you have a powerful toolset given, but by using this doubtful decltype expression, you throw away all the genericity the Standard library gives you and restrict yourself to use of that single std::bind expression. 毕竟你有一个强大的工具集,但是通过使用这个令人怀疑的decltype表达式,你抛弃了标准库给你的所有通用性,并限制自己使用那个单独的std::bind表达式。 That's no good. 那不好。

std::bind requires A as a complete type (see answer by Johannes) and therefore you cannot use it at this point. std :: bind需要A作为完整类型(请参阅Johannes的回答),因此您不能在此时使用它。 As a workaround, if you encapsulate the some_type this will compile : 作为一种解决方法,如果你封装some_type,这将编译

#include <functional>

template <typename T>
class A
{
  void f();
  struct some_type_helper
  {
    typedef decltype(std::bind(&A::f, std::declval<A>())) some_type;
  };
};

template <>
class A<void>
{
  void f();
  struct some_type_helper;
};

struct A<void>::some_type_helper
{
  typedef decltype(std::bind(&A::f, std::declval<A>())) some_type;
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM