2014-10-02 59 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(); 
}