C++ 检测类型是否不可抛出交换的特性,对于msvc也是如此
我需要一个简单的类型特征来检测事物是否不可交换。标准库中没有,所以我写了这个。它在gcc和clang中工作,至少我在几个月的时间里没有遇到任何问题 今天我也在尝试用MSVC 2015进行编译,它给出了一个非常简洁的编译错误,我想了解一下 以下是一个MVCE:C++ 检测类型是否不可抛出交换的特性,对于msvc也是如此,c++,c++11,templates,visual-studio-2015,sfinae,C++,C++11,Templates,Visual Studio 2015,Sfinae,我需要一个简单的类型特征来检测事物是否不可交换。标准库中没有,所以我写了这个。它在gcc和clang中工作,至少我在几个月的时间里没有遇到任何问题 今天我也在尝试用MSVC 2015进行编译,它给出了一个非常简洁的编译错误,我想了解一下 以下是一个MVCE: #include <utility> #include <type_traits> // Code is targetting C++11 so we have to backport this: template
#include <utility>
#include <type_traits>
// Code is targetting C++11 so we have to backport this:
template <bool b, typename V = void>
using enable_if_t = typename std::enable_if<b, V>::type;
namespace detail {
using std::swap;
// Need to use SFINAE for this in case there is no `swap`.
template <typename T, typename ENABLE = void>
struct is_nothrow_swappable : std::false_type {};
template <typename T>
struct is_nothrow_swappable<T, enable_if_t<noexcept(
swap(*static_cast<T *>(nullptr),
*static_cast<T *>(nullptr)))>>
: std::true_type {};
} // end namespace detail
// Tests
static_assert(detail::is_nothrow_swappable<int>::value, "");
static_assert(detail::is_nothrow_swappable<std::pair<int, int>>::value, "");
struct B {};
static_assert(detail::is_nothrow_swappable<B>::value, "");
struct A {
A() = delete;
A(A&&) = delete;
};
static_assert(!detail::is_nothrow_swappable<A>::value, "");
int main() {}
所以我的问题有效地解决了,但问题是,为什么一个有效,另一个失败?我的尝试到底出了什么问题?如果你能解释一下,我将不胜感激。重复这个问题?我认为这个问题与这个问题无关。错误日志末尾的几行类似,但重要的部分是第一个错误,它(似乎)说这个
noexcept
表达式不是一个常量表达式。Idk,是什么让你认为它是一个dupe呢?noexcept
操作符执行编译时检查,如果一个表达式被声明为不抛出任何异常,则返回true。这绝对是一个恒定的表达式是的,我知道noexcept
应该是什么意思,但我不知道的是msvc到底是怎么回事。我猜实际上并不是我的noexcept
没有给出一个常量表达式,错误消息似乎在说,它在std::swap
函数的noexcept
限定符中放的是MSVC头中的任何内容<代码>注意:请参阅正在编译的函数模板实例化“void std::swap(_Ty&,_Ty&)noexcept()”的参考我不完全确定这一行的意思这可能是MSVC错误,因为编译器实例化模板时没有实际类型,然后阻塞了swap的noexcept规范(被检测为不是常量表达式)。此代码足以使MSVC失败:使用std::swap;模板结构是可交换的:std::integral\u constant{};
Error(s):
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\utility(49): error C2057: expected constant expression
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\utility(48): note: see reference to function template instantiation 'void std::swap<T>(_Ty &,_Ty &) noexcept(<expr>)' being compiled
source_file.cpp(6): error C2039: 'type': is not a member of 'std::enable_if<false,V>'
with
[
V=void
]
source_file.cpp(18): error C2061: syntax error: identifier 'type'
source_file.cpp(18): error C2938: 'enable_if_t<false,void>' : Failed to specialize alias template
source_file.cpp(18): error C2059: syntax error: '<end Parse>'
source_file.cpp(24): error C2338:
source_file.cpp(25): error C2338:
source_file.cpp(29): error C2338:
struct do_is_nothrow_swappable
{
template<class T>
static auto test(int) -> std::integral_constant<bool,
noexcept(swap(std::declval<T&>(), std::declval<T&>()))
>;
template<class>
static std::false_type test(...);
};
template <typename T>
struct is_nothrow_swappable : decltype(
do_is_nothrow_swappable::test<T>(0)
)
{};