使用检测惯用法来确定类型是否具有具有特定签名的构造函数

时间:2016-02-27 11:46:48

标签: c++ templates c++14

我正在玩proposal of standard library support for the C++ detection idiom。它是一种类似特征的元函数,用于确定类型<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal"> <View android:layout_width="200dp" android:layout_height="1dp" android:background="#c4c8c9" android:layout_margin="5dp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:text="or" /> <View android:layout_width="200dp" android:layout_height="1dp" android:background="#c4c8c9" android:layout_margin="5dp" /> </LinearLayout> 是否具有名为T的类型成员或具有特定签名的成员函数,例如:

T::type

上面的代码产生了预期的输出

#include <iostream>


template<class...>
using void_t = void;

template<class, template<class> class, class = void_t<>>
struct detect : std::false_type { };

template<class T, template<class> class Operation>
struct detect<T, Operation, void_t<Operation<T>>> : std::true_type { };


template<class T>
using bar_t = decltype(std::declval<T>().bar());

template<class T>
using bar_int_t = decltype(std::declval<T>().bar(0));

template<class T>
using bar_string_t = decltype(std::declval<T>().bar(""));


struct foo
{
    int bar() { return 0; }
    int bar(int) { return 0; }
};


int main()
{
    std::cout << detect<foo, bar_t>{} << std::endl;
    std::cout << detect<foo, bar_int_t>{} << std::endl;
    std::cout << detect<foo, bar_string_t>{} << std::endl;

    return 0;
}

您可以使用live demo进行游戏。现在,我想测试类型1 1 0 是否具有带有特定签名的构造函数,例如T使用其他类型T::T(U)。是否可以使用检测成语来做到这一点?

2 个答案:

答案 0 :(得分:2)

修改detect类以允许变量args:

template <typename...>
using void_t = void;

template <typename AlwaysVoid, template <typename...> class Operation, typename... Args>
struct detect_impl : std::false_type { };

template <template <typename...> class Operation, typename... Args>
struct detect_impl<void_t<Operation<Args...>>, Operation, Args...> : std::true_type { };

添加一个硬编码空类型的别名:

template <template <typename...> class Operation, typename... Args>
using detect = detect_impl<void, Operation, Args...>;
//                         ~~~^

写一个探测器:

template <typename T, typename... Us>
using has_constructor = decltype(T(std::declval<Us>()...));

测试你的课程:

static_assert(detect<has_constructor, foo, foo>{}, "!");

DEMO

答案 1 :(得分:2)

更好:std::is_constructible

template<class U>
struct constructable_from {
  template<class T>
  using test_t = decltype(T(std::declval<U>()));
};

// usage
detect<foo, constructable_from<baz>::test_t> {}

这似乎与您的代码一起使用。可以使用可变参数模板轻松扩展它以支持多参数构造函数。我不知道这是否是&#34;使用检测成语&#34;,但它是我以前使用过的。

我的test code on ideone(它有点乱,我在手机上)