首页 > 解决方案 > 更智能的 is_copy_constructible 用于处理容器

问题描述

我正在尝试编写我自己的 std::is_copy_constructible 版本,它将为仅移动类型的容器返回 false 。

我已经找到了这个答案,描述了如何使它适用于特定的容器类型。现在我正在尝试将其扩展为适用于任何容器。出于我的目的,我将“容器”定义为任何具有“value_type”成员的类。为了确定一个类是否有“value_type”成员,我在这个答案上使用了一个变体。

所以基本上我现在拥有的是:

template <typename T, typename = void>
struct has_value_type : std::false_type {};
template <typename T>
struct has_value_type<T, decltype(std::declval<T>().value_type, void())> : std::true_type {};

用于确定一个类是否具有 value_type 成员,并且:

template <template <typename> class test, typename T>
struct smart_test : test<T> {};
template <template <typename> class test, typename T, typename A>
struct smart_test<test, std::vector<T, A>> : smart_test<test, T> {};
template <typename T>
using smart_is_copy_constructible = smart_test<std::is_copy_constructible, T>;

用于定义适用于向量和非容器类型的 smart_is_copy_constructible。

我想将两者结合起来创建一个适用于所有容器类型(具有 value_type 成员的类型)的 smart_is_copy_constructible 版本。我怀疑我需要以某种方式将 std::enable_if 与我的 has_value_type 结构一起使用,但这是我第一次涉足模板元编程,我不确定如何继续。

到目前为止,我最好的猜测是尝试这个

template <template <typename> class test, typename T>
struct smart_test<test, std::enable_if_t<has_value_type<T>::value> : smart_test<test, typename T::value_type> {};

而不是来自前一个代码块的第二个声明(定义一个专门针对矢量的 smart_test 版本),但这无法编译。

任何帮助将不胜感激!

标签: c++templatessfinaetypetraits

解决方案


是的,std::enable_if_t会这样做:

// I'd recommend following the standard library's naming convention
template<typename T, typename = void>
struct smart_is_copy_constructible : std::is_copy_constructible<T> { };
template<typename T>
struct smart_is_copy_constructible<T, std::enable_if_t<has_value_type<T>::value>> : std::is_copy_constructible<typename T::value_type> { };

template<typename T>
constexpr bool smart_is_copy_constructible_v = smart_is_copy_constructible<T>::value;

神螺栓

has_value_type多半是多余的。您的实现不起作用,并且我在评论中给出的实现足够短,可以内联(不过,正如 Nicol Bolas 建议的那样,您可能想让has_value_type更复杂):

template<typename T, typename = void>
struct smart_is_copy_constructible : std::is_copy_constructible<T> { };
template<typename T>
struct smart_is_copy_constructible<T, std::void_t<typename T::value_type>> : std::is_copy_constructible<typename T::value_type> { };

神螺栓

has_value_type(第一个示例中使用的更正后的是

template <typename T, typename = void>
struct has_value_type : std::false_type {};
template <typename T>
struct has_value_type<T, std::void_t<typename T::value_type>> : std::true_type {};

)


推荐阅读