2017-06-15 68 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}; 
}