2014-10-02 62 views
2
template <typename...dummy> 
class wrapper; 

template < typename TYPE > 
class wrapper <TYPE> {}; 

template < template <typename...> class TYPE, typename... PARAMS > 
class wrapper < TYPE <PARAMS...> > {}; 

template <typename> 
class templated_class {}; 
class normal_class {}; 

typedef wrapper <normal_class> normal_wrapper; 
typedef wrapper < templated_class, int > templated_wrapper; 

错误模板与专业和非特型

'templated_class': class template (not specialized) cannot be a template argument for 'dummy', an actual type was expected

我怎样才能使它发挥作用,使wrapper可以接受normal_classtemplated_class作为第一个参数显然编译上述结果超载?我觉得有一个简单的方法,但我没有看到它,因为我太担心这个问题。

的原因,我不能只写

typedef wrapper < templated_class <int> > templated_wrapper; 

是因为该类型定义是由可变参数宏,它创造的 - 剥离为MCVE目的 - 是这样的:

#define first_va(f,...) f 
#define createwrapper(...) \ 
    typedef wrapper <__VA_ARGS__> first_va(__VA_ARGS__)_wrapper; 

createwrapper(normal_class) 
createwrapper(templated_class,int) 

而且我也没有想法如何执行预处理器向导,以便在<>之后包含所有参数,如果它甚至是可能的话。

使用模板或宏的解决方案对我来说都是可以接受的,尽管我更喜欢模板解决方案。

+0

最后的typedef需要额外的类型名称...在这一点上templated_class不是一个类型(但templated_class 是) - 因此指定'包装的'允许编译器不找'templated_class'立即.....呵呵,你可能需要扩展包装 - 'template class templated_wrapper:public wrapper {};'作为另一个模板类 – Fox 2014-10-02 15:49:51

+0

你不能重载类模板,只专门。而当你专注,你不能改变那种温和的论点。 – 2014-10-02 15:59:11

+0

@Fox'typedef wrapper templated_wrapper'导致相同的错误消息(visual studio 2013)。我不确定你的'templated_wrapper'在我的问题中有什么目的。 – Slyps 2014-10-02 15:59:20

回答

2
#define createwrapper_single(f) \ 
    typedef wrapper<f> f##_wrapper; 
#define createwrapper_multiple(f, ...) \ 
    typedef wrapper<f<__VA_ARGS__> > f##_wrapper; 

#define pick_createwrapper(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, NAME, ...) NAME 
#define createwrapper(...) \ 
    pick_createwrapper(__VA_ARGS__, createwrapper_multiple, createwrapper_multiple, \ 
    createwrapper_multiple, createwrapper_multiple, createwrapper_multiple, \ 
    createwrapper_multiple, createwrapper_multiple, createwrapper_multiple, \ 
    createwrapper_multiple, createwrapper_single, something_is_wrong_if_this_is_used)(__VA_ARGS__) 

Demo。很显然,如果你足够疯狂地编写一个采用9个以上参数的模板,那么这将会中断,但是如果需要的话,你可以根据需要扩展它。


或者,你可以使用decltype和重载函数:

template <template <typename...> class T, typename... params> 
wrapper<T<params...>> wrapper_helper(); 

template <typename T> 
wrapper<T> wrapper_helper(); 

#define first_va(f,...) f 
#define PASTE2(x, y) x##y 
#define PASTE(x, y) PASTE2(x,y) 
#define createwrapper(...) \ 
    typedef decltype(wrapper_helper<__VA_ARGS__>()) \ 
      PASTE(first_va(__VA_ARGS__,_blank), _wrapper); 

Demo

+0

宏观解决方案中非常好的技巧,它解决了我的问题,找出是否有超过1个参数写或不写。用@dyp的想法,我正在编写decltype版本,但你的速度更快。 +1 – Slyps 2014-10-02 16:28:59

0

你不能那样做。一旦您定义了一个模板,其中包含简单的typename类型的所有参数(不包括模板和值),则所有特化必须使用类型作为实际模板参数。相反,如果参数是模板,相应的参数将始终是任何专业化中的模板。也就是说,类模板不会超载。

您正在尝试做不可能的事情,因为您混淆了局部特化中存在的两个括号分隔列表。我想我只是用代码live demo here来解释它。

#include <iostream> 

template <typename...>   // <--- to instantiate, say `wrapper<whatever list of types>` 
struct wrapper 
{ 
    static void foo() { 
    std::cout << "generic" << std::endl; 
    } 
}; 

template<typename T> 
struct wrapper<T>     // <--- to instantiate, say `wrapper<sometype>` 
{ 
    static void foo() { 
    std::cout << "one argument" << std::endl; 
    } 
}; 

// just an illustration 
template <typename T>    // <--------------------------------------------------+ 
struct wrapper <int, double, T> // <--- to instantiate, use this list of arguments | 
{         //   not this one -----------------------------+ 
            //   that is, say `wrapper<int, double, sometype>` 
            //   not `wrapper<sometype>` 
    static void foo() { 
    std::cout << "three arguments (int, double, something)" << std::endl; 
    } 
}; 

template <template<typename ...> class T, // <-----------------------------------------+ 
     typename K>    //             | 
struct wrapper<T<K>>    // <--- to instantiate, use this list of arguments | 
{         //   not this one ------------------------------+ 
            //   that is, say `wrapper<sometemplate<sometype>>` 
    static void foo() { 
     std::cout << "the template thingy" << std::endl; 
    } 
}; 

template <typename> class X {}; 

int main() 
{ 
    wrapper<int, int>::foo(); 
    wrapper<int>::foo(); 
    wrapper<int, double, X<int>>::foo(); 
    wrapper<X<int>>::foo(); 
}