2014-08-28 5 views
1

아래 코드 (길이에 대해서는 사과하겠습니다 만 오류를 재현하는 유일한 방법입니다)는 VS2013을 사용하여 컴파일되지 않습니다. 빈 매개 변수 팩을 확장하는 것과 관련이있는 것 같습니다. 그러나 을 제거하면 main()에서 세 줄 중이 나오기 때문에 컴파일 오류가 사라집니다.VS2013 Variadic 템플릿 컴파일 오류

(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 

질문 : 내가 찾고 있어요

컴파일 오류, 라인 (28) using tuple_t = std::tuple< typename remove_const_and_reference<A>::type... >;과 하나가 P : 특히도 IDEone 때문에 잘 그것을 처리 - 이것은 아마 버그가 있는게 틀림 없어 문제가 될 수있는 이유에 대한 해결 방법과 통찰력이 필요하십니까?

코드 :

1. A 이름 클래스, 당신은 class A의 범위 내에서 template <class A>를 사용하지 않아야합니다 :

#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>(); 
} 

답변

2

그것은 VS2013에서 작업 할 수 있습니다. ,

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. 나는 당신에게 구조체를하지 않는 (그 자체를 상속하는 이유?)로 변경 : 이제 Args을 가정 해 봅시다으로 매개 변수 팩의 이름을 바꿉니다 생산

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

나쁜 생각, 하지만 문제가되지 않습니다. – stijn

+0

@stijn : CallCore에서 A의 이름이 바뀌면 작동합니다. –

+0

그것은 나를위한 것이 아닙니다. 모든 A를 Args로 이름을 바꾸더라도 문제가 남아 있습니다. 또한 afaik C++ 11 이름 분석 규칙은 A가 외부 클래스 A로 취급되어서는 안되지만 템플릿 인수 A로 취급되어야한다고 말합니다.이 경우 VS에는 문제가 없습니다. 어쨌든, 질문을 편집하여 이제는 명확성을위한 Args를 갖습니다. – stijn