gpt4 book ai didi

c++ - 将模板参数从类型更改为非类型如何使 SFINAE 工作?

转载 作者:可可西里 更新时间:2023-11-01 18:02:25 26 4
gpt4 key购买 nike

来自cppreference.com关于 std::enable_if 的文章,

Notes
A common mistake is to declare two function templates that differ only in their default template arguments. This is illegal because default template arguments are not part of function template's signature, and declaring two different function templates with the same signature is illegal.

/*** WRONG ***/

struct T {
enum { int_t,float_t } m_type;
template <
typename Integer,
typename = std::enable_if_t<std::is_integral<Integer>::value>
>
T(Integer) : m_type(int_t) {}

template <
typename Floating,
typename = std::enable_if_t<std::is_floating_point<Floating>::value>
>
T(Floating) : m_type(float_t) {} // error: cannot overload
};

/* RIGHT */

struct T {
enum { int_t,float_t } m_type;
template <
typename Integer,
typename std::enable_if_t<std::is_integral<Integer>::value, int> = 0
>
T(Integer) : m_type(int_t) {}

template <
typename Floating,
typename std::enable_if_t<std::is_floating_point<Floating>::value, int> = 0
>
T(Floating) : m_type(float_t) {} // OK
};

我很难理解为什么 *** WRONG *** *** RIGHT*** 版本无法编译版本确实如此。解释和例子对我来说是 cargo 崇拜。上面所做的只是将类型模板参数更改为非类型模板参数。对我来说,这两个版本都应该有效,因为它们都依赖于 std::enable_if<boolean_expression,T>有一个名为 type 的 typedef 成员, 和 std::enable_if<false,T>没有这样的成员。替换失败(这不是错误)应该会导致两个版本。

看看标准,它说在 [temp.deduct] 中

when a function template specialization is referenced, all of the template arguments shall have values

然后是

if a template argument has not been deduced and its corresponding template parameter has a default argument, the template argument is determined by substituting the template arguments determined for preceding template parameters into the default argument. If the substitution results in an invalid type, as described above, type deduction fails.

这种类型推导失败不一定是错误,这就是 SFINAE 的全部意义所在。

为什么更改 *** WRONG *** 中的 typename 模板参数版本到非类型名称参数使 *** RIGHT ***版本“正确”?

最佳答案

主要是因为[temp.over.link]/6不谈模板默认参数:

Two template-heads are equivalent if their template-parameter-lists have the same length, corresponding template-parameters are equivalent, and if either has a requires-clause, they both have requires-clauses and the corresponding constraint-expressions are equivalent. Two template-parameters are equivalent under the following conditions:

  • they declare template parameters of the same kind,

  • if either declares a template parameter pack, they both do,

  • if they declare non-type template parameters, they have equivalent types,

  • if they declare template template parameters, their template parameters are equivalent, and

  • if either is declared with a qualified-concept-name, they both are, and the qualified-concept-names are equivalent.

然后通过 [temp.over.link]/7 :

Two function templates are equivalent if they are declared in the same scope, have the same name, have equivalent template-heads, and have return types, parameter lists, and trailing requires-clauses (if any) that are equivalent using the rules described above to compare expressions involving template parameters.

...第一个示例中的两个模板是等效的,而第二个示例中的两个模板不是。因此,您的第一个示例中的两个模板声明了相同的实体,并导致 [class.mem]/5 的结构不正确:

A member shall not be declared twice in the member-specification, ...

关于c++ - 将模板参数从类型更改为非类型如何使 SFINAE 工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55667758/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com