【问题标题】:Template specialization vs using if else on template parameter type模板专业化与在模板参数类型上使用 if else
【发布时间】:2018-06-25 05:55:48
【问题描述】:

假设我们有一个模板化函数,其中一小部分代码依赖于模板参数类型。从设计 POV(或任何 POV)来看,哪个更好!使用 if else 检查参数类型,使用type_traits(我们可以使用is_same)或模板特化(我们可以把那个小部分放在另一个我们可以特化的函数中)?

template <typename T>
void func(T log) {
    // common part

    // part dependent on T. We can put this in a separate function which we can specialize.
    // or we can do:
    // if (std::is_same<T, type1>::value) {
    //    //code1;
    // } else if (std::is_same<T, type2>::value) {
    //    //code2;
    // } else {
    //    //generic code;
    // }

    // common part
}

【问题讨论】:

  • 请举两个例子。尽量避免提出主要基于意见的问题的印象。
  • 在 type 上使用 if-else 总是一个糟糕的选择(它往往会使您的代码变得脆弱并且成为维护的噩梦)。特化、重载或继承/多态总是更好的选择。
  • @Someprogrammerdude 您能否详细说明选择该设计的原因?
  • @Yunnosch 为什么你认为这主要是基于意见的?一个设计要么是好的 XOR 要么是坏的。
  • “一个设计要么是好的 XOR 坏的。” - 错误。不同的应用有不同的考虑。一个对一个人来说很糟糕的设计可能只是另一个人的门票。这就是为什么任何关于设计的讨论都会列出备选方案以及每种方案的优缺点。

标签: c++ templates typetraits


【解决方案1】:

使用运行时if 是个坏主意,因为编译时已经知道一切。这正是 c++ 为您提到的这种情况引入 constexpr if 的原因。 constexpr if 需要一个兼容 c++17 的编译器,2018 年应该是这种情况:-)

template <typename T>
void func(T ) {
    std::cout << "common before" << std::endl;

     if constexpr (std::is_same<T, int>::value) {
         std::cout << "int" << std::endl;
     } else if constexpr (std::is_same<T, double>::value) {
         std::cout << "double" << std::endl;
     } else {
         std::cout << "other" << std::endl;
     }

     std::cout << "common after" << std::endl;
}

int main()
{
    func(1);
    func(1.1);
    func('a');
}

但是有一点你应该提一下:如果你的模板函数中有一个很大的“共同”部分,不管你是模板专业化还是constexpr if,你都会得到每个模板的完整代码副本实例。因此,最好将该代码移动到一个函数中,以便只获取一次公共部分。如果编译器认为内联该代码是一个不错的选择,它就会这样做,并且您可以充分利用这两种解决方案。

【讨论】:

  • 正确,但恕我直言,您还应该明确指出 if constexpr 从 C++17 开始可用。
  • @max66:是的,我会添加它。在 2018 年对 c++ 提出问题意味着 c++17 标准。如果没有,人们应该使用较旧的 c++ 标准版本进行标记。这就是我在 SO 上不时读到的内容。
猜你喜欢
  • 2022-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多