对于msvc,也检测类型是否为无法自动交换的特征

时间:2016-11-16 04:51:21

标签: 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 <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() {}

rextester.com我重现上述错误:

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: 

好吧,MSVC说这不是一个持续的表达,而是究竟是什么以及为什么?

这基本上是msvc constexpr支持的错误吗?

或者,这是“表达SFINAE”的意思,错误是因为msvc不支持它?如果是这样我可以解决它吗?

这实际上不是有效的C ++ 11代码,它恰好被gcc和clang接受了吗?

浏览后,我找到了std::is_nothrow_swappable的工作组提案,其附录和示例代码与我的有所不同:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0185r1.html#Appendix

此实现在所有计算机上编译:

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)
)
{};

所以我的问题得到了有效解决,但问题是,为什么实际上一个工作而另一个工作失败?我的尝试究竟出了什么问题?如果你能解释我会非常感激。

0 个答案:

没有答案