【问题标题】:VS2013 Variadic template compilation errorVS2013 可变参数模板编译错误
【发布时间】:2014-08-28 11:34:04
【问题描述】:

下面的代码(对它的长度表示歉意,但这是我发现重现错误的唯一方法)无法使用 VS2013 编译。它似乎与扩展一个空参数包有关。但是,当我删除 main() 中的三行中的 any 时,编译错误就会消失。这让我相信这可能是一个错误 - 特别是因为IDEone 处理得很好:P

编译错误,第28行是using tuple_t = std::tuple< typename remove_const_and_reference< A >::type... >;

(28): error C3548: 'A' : parameter pack cannot be used in this context
   (19): see reference to function template instantiation 'void A::CallCore<Ret,>(Ret (__cdecl *)(void))' being compiled
   with
   [
       Ret=Foo *
   ]
   (50): see reference to function template instantiation 'void A::Call<T*,>(Ret (__cdecl *)(void))' being compiled
   with
   [
       T=Foo,Ret=Foo *
   ]
   (77): see reference to function template instantiation 'void B::RegisterConstructor<Foo,>(void)' being compiled
(28): error C2976: 'remove_const_and_reference' : too few template arguments
(28): error C2955: 'remove_const_and_reference' : use of class template requires template argument list
(28): error C2039: 'type' : is not a member of 'remove_const_and_reference'
(28): error C2146: syntax error : missing ',' before identifier 'type'
(28): error C3546: '...' : there are no parameter packs available to expand
(28): error C2065: 'type' : undeclared identifier
(28): error C3544: '_Types': parameter pack expects a type template argument

问题:我正在寻找解决方法并了解为什么会出现问题?

代码:

#include <tuple>
#include <type_traits>

template< class T, class U = typename std::remove_cv< typename std::remove_reference< T >::type >::type >
struct remove_const_and_reference : remove_const_and_reference< U >
{
};

template< class T >
struct remove_const_and_reference< T, T >
{
  typedef T type;
};

class A
{
public:
  template< class Ret, class... Args >
  void Call( Ret f( Args... ) ) { CallCore( f ); }

  template< class Ret, class Obj, class... Args >
  void Call( Ret( Obj::*f )( Args...) ) { CallCore( f ); }

private:
  template< class Ret, class... Args >
  void CallCore( Ret f( Args... ) )
  {
    using tuple_t = std::tuple< typename remove_const_and_reference< Args >::type... >;
  }

  template< class Ret, class Obj, class... Args >
  void CallCore( Ret( Obj::*f )( Args...) )
  {
    using tuple_t = std::tuple< typename remove_const_and_reference< Args >::type... >;
  }
};

template< class T, class... Args >
T* New( Args&&... args )
{
  return new T( std::forward< Args >( args )... );
}

class B
{
public:
  template< class T, class... Args >
  void RegisterConstructor()
  {
    a.Call< T* >( New< T, Args... > );
  }

  template< class Fun >
  void Register( Fun f )
  {
    a.Call( f );
  }

private:
  A a;
};

struct Foo
{
  Foo(){}
  ~Foo(){}
  void FunA( int ){}
};

void FunB( int ){}

int main()
{
  B().Register( FunB );
  B().Register( &Foo::FunA );
  B().RegisterConstructor< Foo >();
}

【问题讨论】:

    标签: c++ c++11 templates compiler-errors variadic-templates


    【解决方案1】:

    让它在 VS2013 中工作:

    1.A 为你的班级命名,你不应该在class A 的范围内使用template &lt;class A&gt;。将您的参数包重命名为Args

    template< class Ret, class Obj, class... Args > // << Use Args name, not A !
    void CallCore( Ret( Obj::*f )( Args...) )
    {
        using tuple_t = std::tuple< typename remove_const_and_reference< Args >::type... >;
    }
    

    2.我不明白你的结构(为什么它会继承自己?),将其更改为:

    template <typename T>
    struct remove_const_and_reference
    {
       using type = typename std::remove_cv< typename std::remove_reference< T >::type >::type;
    };
    

    【讨论】:

    • 在生产中不是一个坏主意,但这不是问题
    • @stijn:当 A 在两个 CallCore 中重命名时它可以工作
    • 它不适合我。即使我将所有A 重命名为Args,问题仍然存在。同样afaik C++11名称解析规则说A不应该被视为外部类A,而是模板参数A,在这种情况下VS没有问题。无论如何,编辑了这个问题,现在为了清楚起见,它有了 Args
    • @stijn:现在怎么样?
    • @stijn:现在它在 VS2013 中编译
    猜你喜欢
    • 2019-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-29
    • 1970-01-01
    • 2018-07-31
    • 1970-01-01
    • 2016-06-05
    相关资源
    最近更新 更多