c++ - 使用额外的不可推导模板参数重载函数是否有效?

标签 c++ templates language-lawyer

以下代码在 gcc (9)、clang (11) 和 msvc (16.28) 下编译并正常工作:

template <class A>
struct X {
    A a;

    constexpr X(A a) : a{a} { }
};

template <class A>
constexpr auto fn(X<A> const& x) {
    return X<A>(x.a - 1);
}


template <class Xs, class A>
constexpr auto fn(X<A> const& x) {
    return Xs(x.a - 1);
}

constexpr X<int> x1{3};
constexpr auto x2 = fn(x1);
constexpr auto x3 = fn<X<double>>(x1);
有两个fn具有相同声明的函数,除了额外的 Xs第二个参数。
我想确定这是标准接受的,而不是这些编译器提供的额外内容?由于所有 3 个都这样做,我想这将是标准的,但你永远不知道。
我还想知道我对为什么这项工作/将成为标准的假设是否正确:
  • 通话中fn(x1) , Xs无法推导出 fn 的第二次重载被轻轻丢弃(SFINAE?)?
  • 通话中fn<Xs>(x1) ,第一个重载将是 fn(X<X<int>>)与参数 x1 不匹配,因此第一个重载也被丢弃?
  • 最佳答案

    There are two fn functions with identical declarations except for the extra Xs parameter in the second one.


    没关系,您可以使用不同的参数或不同的模板参数来重载函数模板。
    • in the call fn(x1), Xs cannot be deduced so the second overload of fn is discarded gently (SFINAE?)?

    是的,除了它不是 SFINAE,而是重载决议。 SFINAE 中的 S 代表替代。当无法推导出模板参数时,不会发生替换。
    它在 [temp.over]/1 中有描述:

    ... For each function template, if the argument deduction and checking succeeds, the template-arguments (deduced and/or explicit) are used to synthesize the declaration of a single function template specialization which is added to the candidate functions set to be used in overload resolution.


    关于第二个项目符号( fn<X<double>>(x1) ),两个模板都可以合成一个有效的声明,但 X<int>不能转换为 X<X<double>> ,因此选择第二个重载作为唯一可行的重载。
    注意:当多个模板重载可行时,partial ordering执行以确定最专业的模板。

    关于c++ - 使用额外的不可推导模板参数重载函数是否有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68708614/

    相关文章:

    c++ - tinyXml如何添加一个元素

    c++ - Cuda C++ 内存包装器类

    wpf - 轻量级可模板 WPF 形状

    c++ - 未找到使用表达式模板化的静态 constexpr 成员函数

    c++ - 合格的 friend 功能模板实例化

    .net - 如何将 COM 数组传递给托管代码?

    c++ - 复制 boost::function 是否也复制闭包?

    c++ - ' vector 迭代器不兼容'

    java - 是否存在不必要的分号语法错误?

    c++ - 如果从未通过它们进行修改,是否允许对实际 const 对象的引用进行 const 转换?