如何使用 SFINAE 检测 noexcept 方法
How to detect a noexcept method using SFINAE
我问的是一个(热门)问题的变体 - 检测 class 方法的存在。
我在 SO 中阅读了很多答案,大多数 (post C++17) 解决方案看起来像 this:
#include <type_traits>
template<class ...Ts>
struct voider{
using type = void;
};
template<class T, class = void>
struct has_foo : std::false_type{};
template<class T>
struct has_foo<T, typename voider<decltype(std::declval<T>().foo())>::type> : std::true_type{};
基本上,我们让编译器决定使用 "trick" :
如果表达式 std::declval<T>().foo()
格式正确,
那么 decltype(std::declval<T>().foo())
不会产生编译器错误,
然后编译器 "prefers" has_foo<T, typename voider<decltype(...)>>::type
因为它不需要用默认类型替换第二个模板类型。
很好,但是我们如何将 noexcept
与它结合起来呢?
我尝试了很多方法,但似乎大多数技术(包括 decltype(declval<type>.my_func())
)
只关心名称、return 类型和参数类型,而不关心 noexcept。
你可以借助 noexpect
operator (C++11 起)。
The noexcept operator performs a compile-time check that returns true if an expression is declared to not throw any exceptions.
例如
template<class T>
struct has_foo<T,
typename voider<decltype(std::declval<T>().foo()),
std::enable_if_t<noexcept(std::declval<T>().foo())>
>::type
> : std::true_type{};
我问的是一个(热门)问题的变体 - 检测 class 方法的存在。
我在 SO 中阅读了很多答案,大多数 (post C++17) 解决方案看起来像 this:
#include <type_traits>
template<class ...Ts>
struct voider{
using type = void;
};
template<class T, class = void>
struct has_foo : std::false_type{};
template<class T>
struct has_foo<T, typename voider<decltype(std::declval<T>().foo())>::type> : std::true_type{};
基本上,我们让编译器决定使用 "trick" :
如果表达式 std::declval<T>().foo()
格式正确,
那么 decltype(std::declval<T>().foo())
不会产生编译器错误,
然后编译器 "prefers" has_foo<T, typename voider<decltype(...)>>::type
因为它不需要用默认类型替换第二个模板类型。
很好,但是我们如何将 noexcept
与它结合起来呢?
我尝试了很多方法,但似乎大多数技术(包括 decltype(declval<type>.my_func())
)
只关心名称、return 类型和参数类型,而不关心 noexcept。
你可以借助 noexpect
operator (C++11 起)。
The noexcept operator performs a compile-time check that returns true if an expression is declared to not throw any exceptions.
例如
template<class T>
struct has_foo<T,
typename voider<decltype(std::declval<T>().foo()),
std::enable_if_t<noexcept(std::declval<T>().foo())>
>::type
> : std::true_type{};