2013-02-01 143 views
1

編輯:讓我們suposse我有兩個(或多個)模板函數f和使用g(有時),這取決於它的模板參數類型:模板別名

template<typename T> 
some_ugly_and_large_or_deep_template_struct_1<T>::type 
f(const some_ugly_and_large_or_deep_template_struct_1<T>::type&, 
    const some_ugly_and_large_or_deeptemplate_struct_1<T>::type&) 
{ 
    // body, that uses perhaps more times my 
    // "some_ugly_and_large_or_deep_template_struct_1<T>" 
} 

template<typename T> 
some_ugly_and_large_or_deep_template_struct_2<T>::type 
g(const some_ugly_and_large_or_deep_template_struct_2<T>::type&, 
    const some_ugly_and_large_or_deeptemplate_struct_2<T>::type&) 
{ 
    // body, that uses perhaps more times my 
    // "some_ugly_and_large_or_deep_template_struct_2<T>" 
} 

我怎麼能簡化這種「類型」定義?例如使用任何新的C++ 11工具?我認爲只有在這樣的:

template<typename T, 
     typename aux = some_ugly_and_large_or_deep_template_struct_1<T>::type> 
aux f(const aux&, const aux&) 
{ 
    // body, that uses perhaps more times my 
    // "aux" type 
} 

template<typename T, 
     typename aux = some_ugly_and_large_or_deep_template_struct_2<T>::type> 
aux g(const aux&, const aux&) 
{ 
    // body, that uses perhaps more times my 
    // "aux" type 
} 

,我用這種方法看到的問題是,用戶可以提供自己的aux類型,而不是我想要的類型。

+1

爲了確保類型是你願意,你可以使用'static_assert'與'的std :: is_same'什麼。 – hmjd

+0

@hmjd但是我應該'寫'兩次包含'some_ugly_and_large_or_deep_template_struct :: type'的行,並且我可以有許多具有相同問題的功能(並且還降低了可讀性)。 –

+0

與宏? :#define DEEP_TYPE(T)some_ugly_and_large_or_deep_template_struct :: type – Francois

回答

4

如果你讓一個可變參數模板,調用者有沒有可能定義後列出的類型參數:

template<typename T, 
     typename..., // firewall, absorbs all supplied arguments 
     typename aux = some_ugly_and_large_or_deep_template_struct_1<T>::type> 
aux f(const aux&, const aux&) 
{ 
    // body, that uses perhaps more times my 
    // "aux" type 
} 

可選,防止調用f意外太多的模板參數,可以添加一個static_assert :

template<typename T, 
     typename... F, 
     typename aux = some_ugly_and_large_or_deep_template_struct_1<T>::type> 
aux f(const aux&, const aux&) 
{ 
    static_assert(sizeof...(F)==0, "Too many template arguments"); 
    // body, that uses perhaps more times my 
    // "aux" type 
} 

通常情況下,我可以讓用戶定義喜歡aux類型的生活,是例如返回類型,其中這可以爲您節省演員。

或者你可以用enable_if更換static_assert

template<typename T, 
     typename... F, typename = typename std::enable_if<sizeof...(F)==0>::type, 
     typename aux = some_ugly_and_large_or_deep_template_struct<T>::type,> 
aux f(const aux&, const aux&) 
{ 
    // body, that uses perhaps more times my            
    // "aux" type                   
} 
+0

Excel trick the variadic template :)是否可以將variadic模板與'enable_if'結合來擦除'static_assert'? –

+0

當然,我完全忘了那個。謝謝:) – ipc

+0

是否有可能創建一個''類,使防火牆和'sizeof'檢查,並把這個'class'作爲模板參數?這個想法是最簡單的,因爲我在我的代碼中有很多點都有同樣的問題。 –

1

一個可能的解決方案是將模板函數轉換爲template structoperator()。例如:

#include <iostream> 
#include <string> 

template <typename T> 
struct some_ugly_and_large_or_deep_template_struct 
{ 
    typedef T type; 
}; 

template <typename T> 
struct f 
{ 
    typedef typename some_ugly_and_large_or_deep_template_struct<T>::type aux; 

    aux operator()(const aux& a1, const aux& a2) 
    { 
     return a1 + a2; 
    } 
}; 

int main() 
{ 
    std::cout << f<int>()(4, 4) << "\n"; 
    std::cout << f<std::string>()("hello ", "world") << "\n"; 
    return 0; 
} 
+0

好,但有一個反對意見:如果我有很多函數,並且每個函數都有不同的'some_ugly_and_large_or_deep_template_struct'? –

+0

@ Peregring-lk,我不確定你的意思到底是什麼? – hmjd

+0

我編輯了更具體的問題。 –

2

你可以宣佈一個模板別名旁邊的功能:

template<typename T> using f_parameter 
    = typename some_ugly_and_large_or_deep_template_struct<T>::type; 

template<typename T> 
f_parameter<T> f(const f_parameter<T>&, const f_parameter<T>&) 
{ 
    f_parameter<T> param; 
} 
+0

更好,但是這個「別名」是在整個編譯單元中從定義點到最終定義的,也許我用不同的'f_parameters'有不同的功能。 –

+0

+1我想知道'使用'會在這裏提供一個解決方案,但語法逃脫了我。 – hmjd

+0

@ Peregring-lk,所以你可以寫'f_parameter'和'g_parameter',可能將它們放在''detail'命名空間中。 – ecatmur

1

您可以在合適的命名空間中使用類似

namespace f_aux { 
    template <typename T> using type = 
      typename some_ugly_and_large_or_deep_template_struct<T>::type; 
} 

template <typename T> 
f_aux::type<T> f(const f_aux::type<T>& , const f_aux::type<T>&); 

如果f的聲明或類,則可能不需要額外的f_aux名稱空間。