std::enable_if 与非即时上下文中的硬错误
std::enable_if vs hard errors in non-immediate context
根据 SFINAE 在 cpprefence
上的描述
Only the failures in the types and expressions in the immediate context of the function type or its template parameter types or its explicit specifier (since C++20) are SFINAE errors. If the evaluation of a substituted type/expression causes a side-effect such as instantiation of some template specialization, generation of an implicitly-defined member function, etc, errors in those side-effects are treated as hard errors.
特别是,当我下面的代码中的 Helper<T>
在模板参数推导期间被实例化时,我收到了一个错误,正如预期的那样。所以这是我的问题:为什么 std::enable_if
与
SFINAE,即使它是一个必须实例化的结构(并且通常与
很多类型特征结构也在这个过程中被实例化)。
这是代码
#include<iostream>
#include<type_traits>
template<typename T, typename U = typename T::my_type>
void sfinae(const T&) { std::cout << "template\n"; }
void sfinae(...) { std::cout << "non template\n"; }
template<typename T>
struct Helper{
using my_type = typename T::my_type;
};
template<typename T, typename U = typename Helper<T>::my_type>
void hardError(const T&) { std::cout << "template\n"; }
void hardError(...) { std::cout << "non template\n"; }
struct NonEmpty{ using my_type=int; };
struct Empty{ };
int main()
{
NonEmpty ne;
Empty e;
sfinae(ne); //template overload called
hardError(ne); //template overload called
sfinae(e); //non-template overload called
hardError(e); //hard error
}
std::enable_if
的可能实现是
template <bool cond, typename T = void> struct enable_if;
template <typename T> struct enable_if<false, T>{};
template <typename T> struct enable_if<true, T>{ using type = T; };
所以enable_if
不会产生硬错误。实例化 std::enable_if<false>
有效。
实例化 Helper<Empty>
在 Empty::type
上产生错误,这不是在 SFINAE 的直接上下文中完成的,因此是硬错误。
std::enable_if
和 std::void_t
与 SFINAE 配合得很好,因为它们提供了在直接上下文中失败的简单方法:
std::enable_if<cond_v<T>, int>::type = 0
或 typename AlwaysVoid = std::void_t<decltype(dependent_expression)>
.
根据 SFINAE 在 cpprefence
上的描述Only the failures in the types and expressions in the immediate context of the function type or its template parameter types or its explicit specifier (since C++20) are SFINAE errors. If the evaluation of a substituted type/expression causes a side-effect such as instantiation of some template specialization, generation of an implicitly-defined member function, etc, errors in those side-effects are treated as hard errors.
特别是,当我下面的代码中的 Helper<T>
在模板参数推导期间被实例化时,我收到了一个错误,正如预期的那样。所以这是我的问题:为什么 std::enable_if
与
SFINAE,即使它是一个必须实例化的结构(并且通常与
很多类型特征结构也在这个过程中被实例化)。
这是代码
#include<iostream>
#include<type_traits>
template<typename T, typename U = typename T::my_type>
void sfinae(const T&) { std::cout << "template\n"; }
void sfinae(...) { std::cout << "non template\n"; }
template<typename T>
struct Helper{
using my_type = typename T::my_type;
};
template<typename T, typename U = typename Helper<T>::my_type>
void hardError(const T&) { std::cout << "template\n"; }
void hardError(...) { std::cout << "non template\n"; }
struct NonEmpty{ using my_type=int; };
struct Empty{ };
int main()
{
NonEmpty ne;
Empty e;
sfinae(ne); //template overload called
hardError(ne); //template overload called
sfinae(e); //non-template overload called
hardError(e); //hard error
}
std::enable_if
的可能实现是
template <bool cond, typename T = void> struct enable_if;
template <typename T> struct enable_if<false, T>{};
template <typename T> struct enable_if<true, T>{ using type = T; };
所以enable_if
不会产生硬错误。实例化 std::enable_if<false>
有效。
实例化 Helper<Empty>
在 Empty::type
上产生错误,这不是在 SFINAE 的直接上下文中完成的,因此是硬错误。
std::enable_if
和 std::void_t
与 SFINAE 配合得很好,因为它们提供了在直接上下文中失败的简单方法:
std::enable_if<cond_v<T>, int>::type = 0
或 typename AlwaysVoid = std::void_t<decltype(dependent_expression)>
.