代码之家  ›  专栏  ›  技术社区  ›  cigien Jorge Eldis

当不需要检查收缩时,是否需要实例化函数定义?

  •  1
  • cigien Jorge Eldis  · 技术社区  · 6 年前

    考虑下面的程序:

    template<typename T>
    constexpr int f() 
    {
        T{}.i; // error if instantiated with [T = double]
        return 42;
    }
    
    constexpr void g(char);
    
    using U = decltype( g( {f<double>()} ) );
    

    据我所知,最后一行是错误的,因为调用 f<double>() 在括号初始值设定项中,即使 f<T> 返回一个 int ,返回的值 智力 需要决定是否可以缩小到 char 正如预期的那样 g .这需要定义 f 用 double ,这会导致错误。gcc和clang都拒绝使用此代码。


    然而,如果 G 更改为接受 智力 参数:

    constexpr void g(int);
    

    那么,似乎没有必要实例化 F 自缩小转换以来 必须 达到目的事实上,gcc接受这一点,但clang仍在实例化 F 具有 双重的 拒绝接受 code .此外,如果 F 只声明了,但没有定义,clang接受代码,这意味着不需要定义,也不应该实例化。

    我的推理正确吗?这是一个叮当作响的错误,还是需要实例化,这实际上是一个gcc错误?

    0 回复  |  直到 6 年前
        1
  •  2
  •   Jeff Garrett    6 年前

    这是 CWG #1581 我想,通过 P0859 .

    temp.inst/5 说:

    除非函数模板专门化是声明的专门化,否则在需要函数定义存在的上下文中引用专门化时,或者如果定义的存在影响程序的语义,则隐式实例化函数模板专门化。

    存在是否会影响程序的语义?

    temp.inst/8 说:

    如果表达式([expr.const])需要对变量或函数进行常量计算,则变量或函数定义的存在会影响程序的语义,即使不需要对表达式进行常量计算,或者常量表达式计算不使用该定义。

    表达式的常量求值是否需要它?

    expr.const/15.6-7 说:

    如果函数或变量是:

    • 一个constepr函数,由一个可能是常量的表达式命名,或
    • 一种变量,其名称显示为一个可能的常量计算表达式,它是一个constexpr变量,或者是非易失的const限定整数类型或引用类型。

    它是由一个可能是常量的表达式命名的吗?

    expr.const/15.1-15.5 说:

    如果表达式或转换满足以下条件,则它可能是常量:

    • 一个明显恒定的求值表达式,
    • 一个可能经过计算的表达式,
    • 大括号初始化列表的立即子表达式,
    • 形式的表达&在模板化实体中出现的强制转换表达式,或
    • 上述任一操作数的子表达式,它不是嵌套的未赋值操作数的子表达式。

    它是带括号的init列表的直接子表达式。