【问题标题】:Can I get name / reference to specialization value inside template specialization?我可以在模板专业化中获取专业化值的名称/引用吗?
【发布时间】:2021-04-12 20:55:24
【问题描述】:

我的代码:

enum class list{one, two};
template <list T> class Base;
template <> class Base <list::one>{
    A a{list::one};
    B b{list::one};
    C c{list::one};
};
template <> class Base <list::two>{
    B b{list::two};
    C c{list::two};
    D d{list::two};
};

但我想避免重复代码,并使用对专业化值的引用,如下所示:

template <> class Base <list::one>{
    A a{T};
    B b{T};
    C c{T};
};
template <> class Base <list::two>{
    B b{T};
    C c{T};
    D d{T};
};

我可以使污泥临时变量,但看起来也不好:

template <> class Base <list::one>{
    list T = list::one;
    A a{T};
    B b{T};
    C c{T};
};

有什么方法可以参考模板特化值吗?

【问题讨论】:

  • 恐怕使变量是唯一的选择。只需确保将static constexpr 添加到其中,其行为方式与模板参数相同。

标签: c++ c++11 templates template-meta-programming


【解决方案1】:

在以下示例中,我使用 SFINAE 使 TBase 的定义中可用。具体来说,我做了以下事情:

  • 向主模板添加了一个虚拟类型参数,
  • 通过指定参数T(并指定第二个虚拟类型参数)使两个专业化部分化,
  • 通过std::enable_if_t 指定了第二个虚拟类型参数,强制T 等于list::onelist::two 在两个特化中。
#include <iostream>
#include <type_traits>

enum class list{one, two};

// to make the code compile
class A { public: A(list) {} };
class B { public: B(list) {} };
class C { public: C(list) {} };
class D { public: D(list) {} };

// primary template (second param's sole purpose is to allow partial spec.)
template <list T, typename = void>
class Base;

// partial specialization #1
template <list T>
class Base <T, std::enable_if_t<T == list::one>>{
    A a{T};
    B b{T};
    C c{T};
  public:
    Base() { std::cout << "list::one\n"; }
};

// partial specialization #2
template <list T>
class Base <T, std::enable_if_t<T == list::two>>{
    B b{T};
    C c{T};
    D d{T};
  public:
    Base() { std::cout << "list::two\n"; }
};

int main() {
    Base<list::one> o;
    Base<list::two> t;
}

这是通过std::enable_if 使用 SFINAE 的一种非常标准的方式。在cppreference page on std::enable_if 上可以找到类似的示例,其中最后一个示例(带有第一个注释// primary template 的示例)重新编码了上面的代码。

【讨论】:

    猜你喜欢
    • 2020-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-18
    • 1970-01-01
    相关资源
    最近更新 更多