【问题标题】:SFINAE on Error in Dependent Type causes unexpected hard errorSFINAE on Error in Dependent Type 导致意外的硬错误
【发布时间】:2020-03-27 18:09:31
【问题描述】:

我有代码可以简化成这样的:

#include <type_traits>

template <typename T>
struct dependent
{
    using type = typename T::type;
};

template <typename T>
typename dependent<T>::type
foo(const T& x);

bool foo(bool x) { return x; }

int main()
{
    foo(true);
}

这无法使用带有--std=c++17 的 g++ 9.3 进行编译,并出现错误:

test.cpp: In instantiation of 'struct dependent<bool>':
test.cpp:11:1:   required by substitution of 'template<class T> typename dependent<T>::type foo(const T&) [with T = bool]'
test.cpp:17:13:   required from here
test.cpp:6:11: error: 'bool' is not a class, struct, or union type
    6 |     using type = typename T::type;
      |           ^~~~

这不是我所期望的。我希望尝试在template &lt;typename T&gt; typename dependent&lt;T&gt;::type foo(const T&amp; x) 中用bool 替换T 会失败,这不是错误。似乎 SFINAE 不适合我,但我不知道为什么。

来自SFINAE上的非官方参考中的示例:

替换按词法顺序进行,并在遇到失败时停止。

template <typename A>
struct B { using type = typename A::type; };

template <
  class T,
  class   = typename T::type,      // SFINAE failure if T has no member type
  class U = typename B<T>::type    // hard error if T has no member type
                                   // (guaranteed to not occur as of C++14)
> void foo (int);

我在class U = typename B&lt;T&gt;::type 上遇到了这个问题,但是“保证不会在 C++14 中发生”位似乎表明从 C++14 开始不应该发生这种情况。什么给了?

【问题讨论】:

  • 该示例旨在说明按词汇顺序进行并在遇到故障时停止。因为替换到第一个默认模板参数失败,所以根本不替换第二个默认模板参数。
  • 该示例演示了我正在寻找的解决方法,但我无法通过查看它来理解:-)

标签: c++ c++14 sfinae


【解决方案1】:

问题是dependent&lt;T&gt; type,但它可能不正确,导致硬故障。

您可以让dependent SFINAE 友好:

template <typename T, typename Enabler = void>
struct dependent
{
};

template <typename T>
struct dependent<T, std::void_t<typename T::type>>
{
    using type = typename T::type;
};

Demo

【讨论】:

  • 更简单:template&lt;class T, class = typename T::type&gt; struct dependent {};?
  • 你能解释一下它是如何格式错误导致硬错误的吗? cppreference 声明“尝试在范围解析运算符 :: 左侧使用不是类或枚举的类型”会导致 SFINAE 错误。
  • @bipll:我更喜欢 void 版本,它更通用。因为它允许额外的专业化(如std::enable_if_t&lt;std::is_floating_point&lt;T&gt;&gt;)。
  • @alterigel: 阅读 "替换发生在" 部分,所以dependent&lt;T&gt;::type 确实是替换,但using type = typename T::type; 不是,它是副作用dependent&lt;T&gt; 实例化,并且“这些副作用中的错误被视为硬错误”
猜你喜欢
  • 2016-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-03
  • 2018-01-16
  • 1970-01-01
  • 2017-04-21
  • 1970-01-01
相关资源
最近更新 更多