【问题标题】:merging template specializations for const and non-const std::list合并 const 和非 const std::list 的模板特化
【发布时间】:2017-06-15 15:46:41
【问题描述】:

对于以下 MWE,是否有一种简单的方法可以将两个模板特化合并为一个,可能使用 std::enable_if

#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”的类型。

【问题讨论】:

  • 您的意思是您要编写一个模板,但同时适用于const 和非const 版本?它们的行为是否相同?

标签: c++ templates c++14 template-specialization


【解决方案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
{
    //...
};

【讨论】:

  • @T.C.:确实不需要,已删除。
【解决方案2】:

对于以下 MWE,是否有一种简单的方法可以将两个模板特化合并为一个,可能使用 std::enable_if?

您是否接受没有std::enable_it 的解决方案?

为了使解决方案更灵活,我建议定义一个类型特征specIndex,以修复类型相关索引,其中0 是“通用类型”,1 是“std::list &@ 987654325@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
 { };

最后一步是定义索引1(std::list&lt;T&gt; &amp;或常量)特化

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};
 }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-11
    相关资源
    最近更新 更多