【问题标题】:Short-circuiting while instantiating template?实例化模板时短路?
【发布时间】:2011-06-03 18:54:49
【问题描述】:

考虑一下这段代码sn-p,

template<bool b>
struct other
{
    static const bool value = !b;
};

template<bool b>
struct test
{
    static const bool value = b || other<b>::value;
};

int main()
{
      bool value = test<true>::value;   
}

编译器是否在上述情况下实例化other&lt;true&gt;,而实例化似乎完全没有必要?或者仅仅因为我写了语法other&lt;b&gt;::value,编译器必须实例化它,而不管它对test&lt;true&gt;::value的值的计算毫无贡献?

我想听听,a) 标准 要求 什么,以及 b) 各种编译器 实际上 实现了什么?标准中的相关部分将不胜感激。

【问题讨论】:

  • 根据“C++ 模板:完整指南”第 307 页,看起来,至少根据标准,不,编译器不会短路这个表达式,并且确实会评估两者分支机构。我不确定这是为什么或者这里更普遍的原则是什么,但这可能至少是您问题的部分答案。
  • 标准不允许他们在这里做“短路”。这就是为什么你需要自己实现它,就像done here。原因很简单:您需要知道other&lt;b&gt;::value 的类型以及它是否完全可以转换为bool 并且有意义。为此,other&lt;b&gt; 需要被实例化。如果它的类型会屈服于被调用的重载op|| 怎么办?那么初始化器将是无效的。

标签: c++ templates instantiation short-circuiting


【解决方案1】:

注意由于C++11中引入了constexpr函数,可以实现短路:

template<bool b>
constexpr bool test_other();

template<bool b>
struct test
{
    static const bool value = b || test_other<b>();
};

int main()
{
    bool value = test<true>::value;
}

...虽然test_other() 未定义,但编译器不会尝试调用它。

很遗憾,这不适用于consteval。在这种情况下,第一级“测试设施”test 本身必须是一个函数:

template<bool b>
consteval bool test_other();

template<bool b>
consteval bool test()
{
    return b || test_other<b>();
};

int main()
{
    bool value = test<true>();
}

【讨论】:

    【解决方案2】:

    根据 C++ 规范,$14.7.1/4 部分:

    "一个类模板特化是 如果类隐式实例化 类型在上下文中使用 需要一个完全定义的对象 键入 或如果 类类型影响语义 程序;特别是,如果一个 类型为类的表达式 模板专业化涉及 重载决议”

    在您使用短路说明的情况下,该类必须具有完整的类型,因为您正在查看它的内部以找到 value 静态成员。这会阻止编译器使表达式短路。

    至于在实践中实际发生了什么,我不确定,因为我看不出编译器不进行实例化是如何逃脱的。例如,假设other&lt;b&gt; 的实例化如下所示:

    template <bool B> struct other {
        typedef int value;
    };
    

    在这里,您的程序格式错误,因为 other&lt;b&gt;::value 是一个类型,而不是一个值,但是编译器无法在没有实际执行实例化的情况下诊断错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-29
      • 2012-03-18
      • 2021-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多