c++ - 什么是实现 is_swappable 以测试 Swappable 概念的正确方法?

标签 c++

我认为 is_swappable 的“正确”实现如下:

template<class T, class U = T> struct is_swappable<T, U> : /* see below */ { }

is_swappable 继承自 std::true_type如果 T 和 U 是 Swappable , 否则来自 std::false_type .


我尝试了很多方法,但 SFINAE 似乎不起作用。这是一个特别讨厌的反例:

struct A {
    A() {}
    ~A() {}
    A(const A&) = delete;
    A(A&&) = delete;
};

显然 A 不是 Swappable .然而,我能提出的任何通用解决方案都无法正确处理上述示例。

我尝试过但没有成功的 SFINAE 实现如下所示:

namespace with_std_swap {
    using std::swap;

    template<class T, class U, class =
        decltype(swap(std::declval<T&>(), std::declval<U&>()))>
    std::true_type swappable_test(int);

    template<class, class> std::false_type swappable_test(...);
}

template<class T, class U = T>
struct is_swappable
: decltype(with_std_swap::using_std_swap::swappable_test<T, U>(0)) { };

有没有办法在没有编译器帮助的情况下编写 is_swappable 代码?

最佳答案

基于@jrok 的回答,我们可以通过编写一个 swap 函数来判断一个不合格的 swap 调用是否会调用 std::swapstd::swap 相同的签名,但可以检查的唯一返回类型:

namespace detail2 {
    struct tag {};

    template<class T>
    tag swap(T&, T&);

    template<typename T>
    struct would_call_std_swap_impl {

        template<typename U>
        static auto check(int)
        -> std::integral_constant<bool, std::is_same<decltype( swap(std::declval<U&>(), std::declval<U&>())), tag>::value>;

        template<typename>
        static std::false_type check(...);

        using type = decltype(check<T>(0));
    };

    template<typename T>
    struct would_call_std_swap : would_call_std_swap_impl<T>::type { };
}

那么is_swappable的定义就变成了:

template<typename T>
struct is_swappable :
    std::integral_constant<bool,
        detail::can_call_swap<T>::value &&
        (!detail2::would_call_std_swap<T>::value ||
        (std::is_move_assignable<T>::value &&
        std::is_move_constructible<T>::value))
    > { };

我们还需要一个特殊情况来交换数组:

template<typename T, std::size_t N>
struct is_swappable<T[N]> : is_swappable<T> {};

关于c++ - 什么是实现 is_swappable 以测试 Swappable 概念的正确方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26744589/

相关文章:

c++ - Visual Studio 2012 - 错误 LNK1104 : cannot open file 'glew32.lib'

使用了 C++ 未初始化的变量

c++ - 静态类成员上未解析的外部符号

c++ - 自定义绘制QMainWindow标题栏

c++ - 为什么在将窄字符串转换为宽字符串时用 0xFF 屏蔽字符?

c++ - linux 中的 force kill 命令 (kill -9) 是否会在 C++ 应用程序中使用 new 运算符清理动态分配的内存?

c++ - 在不复制代码的情况下从工厂实例化对象(例如炮塔)的草图(即原型(prototype))

android - 确定套接字何时在 Android 上关闭

dll 中的 C++ 模板单例

c++ - 在 C++ 应用程序中可以使用什么未知网页编码的字符集检测器?