【问题标题】:SFINAE fails with template non-type reference argumentSFINAE 因模板非类型引用参数而失败
【发布时间】:2019-07-13 14:05:14
【问题描述】:

考虑这段代码:

constexpr int XX = 10;

template < auto& II > struct Ban { };
template < auto& II >
std:: true_type test(Ban<II>*);
std::false_type test(...);

和:

using BB = decltype(test(std::declval<Ban<XX>*>()));

在这里,我希望 BBstd::true_type,但对于 gcc-8.3clang-8.0,它是 std::false_type。这是这些编译器的错误吗?

请注意,当我将 auto&amp; 更改为 auto 时,BB 变为 std::true_type。另请注意,如果我使用int const 而不是autogcc 的情况是相同的,所以int const&amp; 屈服于std::false_type,而int const 屈服于std::true_type,而对于clang @987654341 @ 屈服于 std::true_type。您可以找到实时示例here

是否有一种解决方法可以使用非类型引用的模板来执行这种 SFINAE?关键是要有像IsInstantiationOfBan 这样的实用程序。

【问题讨论】:

  • 我在标准中看不到任何明确说明模板参数推导如何适用于包含占位符类型的非类型模板参数的内容。

标签: gcc clang c++17 sfinae non-type


【解决方案1】:

也许你想要decltype(auto)而不是auto &amp;

#include <type_traits>

constexpr int XX = 10;

template <decltype(auto) II > struct Ban { };
template <decltype(auto) II >
std::true_type test(Ban<II>*);
std::false_type test(...);

int main()
{
    using BB = decltype(test(std::declval<Ban<(XX)>*>()));
                                           // ^  ^ be careful for brackets!

    static_assert(std::is_same_v<BB, std::true_type>);

    return 0;
}

[live demo]

如果您的第一个问题,clang 可能需要在 auto &amp; 之前使用 const 说明符来实现 const 正确性(constexpr 变量也可能是 const)。 [example].

【讨论】:

  • 我怀疑这是一个 Clang 错误,不是吗?
  • @JohannesSchaub-litb 确实,我的回答中并没有明确表示是不是 :)? auto &amp; 也应该与 const 匹配。大概this可以作为参考。
  • 谢谢!我担心模板参数中的auto 会无缘无故地使用与其他地方的auto 不同的规则。因为这是 C++,所以我一点也不惊讶。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-09
相关资源
最近更新 更多