2017-06-15 51 views
2

是否有一種簡單的方法可以將兩個模板專門化合併爲一個簡單的方法,可能使用std::enable_if,用於以下MWE?合併常量和非常量的模板專業化std :: list

#include <string> 
#include <list> 
#include <memory> 

class A { 
    // ... 
}; 
class B { 
    // ... 
}; 

template<typename T> class C {}; 

template<typename T> 
class C<std::list<T> &> : public A, public B 
{ 
    std::list<T> &l_ref; 
public: 
    C(std::list<T> &lr) : l_ref{lr} { } 
    // ... 
}; 

template<typename T> 
class C<const std::list<T> &> : public A, public B 
{ 
    const std::list<T> &l_ref; 
public: 
    C(const std::list<T> &lr) : l_ref{lr} { } 
    // ... 
}; 

對於慣用

template<typename T> 
struct C<T, typename std::enable_if< 
    std::is_same<T, std::list<E> &>::value || 
    std::is_same<T, const std::list<E> &>::value>::type> 
    : public A, public B 
{ 
    // ... 

方式,我看不出有什麼辦法讓E抵扣或指定的「任何std::list」類型。

+0

你的意思是你想編寫一個模板,但兩個'const'和非''const'版本?他們的行爲是否一樣? –

回答

1

您可以創建一個特徵,第一,然後用SFINAE,像:

template <typename T> struct is_a_stdlist_ref : std::false_type {}; 
template <typename ... Ts> 
struct is_a_stdlist_ref<std::list<Ts...>&> : std::true_type {}; 
template <typename ... Ts> 
struct is_a_stdlist_ref<const std::list<Ts...>&> : std::true_type {}; 

template<typename T, typename Enabler = void> struct C; 

template<typename T> 
struct C<T, std::enable_if_t<is_a_stdlist_ref<T>::value>> 
    : public A, public B 
{ 
    //... 
}; 
+1

...那個'void_t'的意義究竟是什麼? –

+0

@ T.C:確實不需要,刪除。 – Jarod42

0

是否有一個簡單的方法來兩個模板特合併成一個單一的一個,也許使用的std :: enable_if,對於以下MWE?

您接受沒有std::enable_it的解決方案嗎?

爲了使解決方案更加靈活,我建議定義一個類型,特點,specIndex,確定一個類型的相關指標,其中0是「通用型」,1是「標準::名單& or const`,等整數可以參考其他特

template <typename> 
struct specIndex 
{ static constexpr std::size_t value { 0U }; }; // generic version 

template <typename T> 
struct specIndex<std::list<T> &> 
{ static constexpr std::size_t value { 1U }; }; // pro lists 

template <typename T> 
struct specIndex<std::list<T> const &> 
{ static constexpr std::size_t value { 1U }; }; // pro lists 

下一步是添加一個默認模板整數參數爲C

template <typename T, std::size_t = specIndex<T>::value> 
class C 
{ }; 

的升AST步驟是定義該指數1(std::list<T> &或常量)專業化

template<typename T> 
class C<T, 1U> : public A, public B 
{ 
    private: 
     T & l_ref; 

    public: 
     C (T & lr) : l_ref{lr} 
     { std::cout << "- list version" << std::endl; } 
}; 

下面是一個完整的例子

#include <string> 
#include <list> 
#include <memory> 
#include <iostream> 

class A 
{ }; 

class B 
{ }; 

template <typename> 
struct specIndex 
{ static constexpr std::size_t value { 0U }; }; // generic version 

template <typename T> 
struct specIndex<std::list<T> &> 
{ static constexpr std::size_t value { 1U }; }; // pro lists 

template <typename T> 
struct specIndex<std::list<T> const &> 
{ static constexpr std::size_t value { 1U }; }; // pro lists 

template <typename T, std::size_t = specIndex<T>::value> 
class C 
{ }; 

template<typename T> 
class C<T, 1U> : public A, public B 
{ 
    private: 
     T & l_ref; 

    public: 
     C (T & lr) : l_ref{lr} 
     { std::cout << "- list version" << std::endl; } 
}; 

int main() 
{ 
    std::list<long> sll; 

    C<int>      a; 
    C<std::list<long> &>  b{sll}; 
    C<std::list<long> const &> c{sll}; 
}