【问题标题】:Conditional code depending on template parameters comparision取决于模板参数比较的条件代码
【发布时间】:2018-07-07 19:37:28
【问题描述】:

大家!想要根据模板参数进行不同的方法编译。

template <unsigned long prec> class DFixed {
public:
  unsigned long val;
...
  template <unsigned long prec1> DFixed<prec> &operator-=(DFixed<prec1> d) {
    #if prec==prec1
    val -= d.val;
    #elif prec<prec1
    val -= d.val/(prec1/prec);
    #else
    val -= d.val*(prec/prec1);
    #endif
    return *this;
  }
...
};

但是上面的代码调用 block for prec==prec1 即使对于不同的 prec。

【问题讨论】:

  • 您的预处理器和模板编程的组合不起作用。请改用if ()else。不要担心“死代码”路径。编译器(非常)可能能够优化它们。 (如果有疑问,请查看程序集输出。);-)
  • 感谢您的回答!它有效,但编译器抱怨零除。这是警告,但这就是我开始尝试预处理器的原因。你知道一些在编译时比较模板参数并进行条件编译的方法吗?
  • 如果你可以使用 c++17,你可以使用 if constexpr。
  • 如果您确定带有prec == 0(或prec1 == 0)的分支未处于活动状态,那么我不会太在意警告。它表明编译器确实将 precprec1 解析为值(这是最终优化的前提条件,它消除了相应的 if 分支,甚至是 if ()s 本身。)
  • 虽然:else if (prec &lt; prec1) 确实可以导致该分支变得活跃,例如prec == 0prec1 &gt; 0。恐怕您必须修改代码(附加if 条件)以防止正确除以0。 (虽然编译器的警告是有道理的。)

标签: c++ templates conditional-compilation


【解决方案1】:

如前所述,C++17 的if constexpr 是最好的解决方案:

template <unsigned long prec1>
DFixed & operator-=(DFixed<prec1> d) {
    if constexpr (prec==prec1)
        val -= d.val;
    else if constexpr (prec<prec1)
        val -= d.val/(prec1/prec);
    else
        val -= d.val*(prec/prec1);

    return *this;
}

如果您使用的是 C++11,则可以使用 SFINAE,并将 std::enable_if 隐藏在 REQUIRES 宏中:

#define REQUIRES(...) typename std::enable_if<(__VA_ARGS__), int>::type = 0
template <unsigned long prec1, REQUIRES(prec==prec1)>
DFixed & operator-=(DFixed<prec1> const & d) {
    val -= d.val;
    return *this;
}
template <unsigned long prec1, REQUIRES(prec<prec1)>
DFixed & operator-=(DFixed<prec1> const & d) {
    val -= d.val/(prec1/prec);
    return *this;
}
template <unsigned long prec1, REQUIRES(prec>prec1)>
DFixed & operator-=(DFixed<prec1> const & d) {
    val -= d.val*(prec/prec1);
    return *this;
}

请注意,输入参数dconst 引用传递以避免不必要的复制。

【讨论】:

    【解决方案2】:

    看来你想使用类似的东西

    if constexpr (prec == prec1) {
        // one branch
    }
    else {
        // other branch
    }
    

    if constexpr 是在 C++17 中引入的。

    【讨论】:

    • 谢谢!我可以在 C++11 中做点什么吗?
    • 可以,但很烦人。例如,您可以使用struct 模板的特化(一次用于指示值相同的模板参数,一次用于不同的值)并委托给它。使用 C++14,您可以使用 std::condition 之类的东西和两个通用 lambda。无论哪种方式都可以做到,但有点烦人。
    猜你喜欢
    • 2017-04-02
    • 1970-01-01
    • 1970-01-01
    • 2011-08-05
    • 1970-01-01
    • 1970-01-01
    • 2012-07-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多