问题描述
假设我不想编写一个概念(或者我的编译器不支持它们)并且没有匹配的类型特征,是否存在C ++ 20 non void_t方法来检查是否可以使用参数B和C构造A?
注意:这是toy example,真正的问题是void_t还是检查概念是否在C ++ 20中编译的最佳方法。
template <typename A,typename B,typename C,typename = void>
struct my_is_constructible : std::false_type {};
template <typename A,typename C>
struct my_is_constructible <A,B,C,std::void_t<decltype(A(std::declval<B>(),std::declval<C>()))>>
: std::true_type {};
解决方法
您可以使用检测到的惯用语,它是对void_t
的抽象。如果没有这些概念,这几乎是您可以获得的最接近的概念:
template <typename Default,typename AlwaysVoid,template<typename...> typename Op,typename... Args>
struct detector {
using value_t = std::false_type;
using type = Default;
};
template <typename Default,typename... Args>
struct detector<Default,std::void_t<Op<Args...>>,Op,Args...> {
using value_t = std::true_type;
using type = Op<Args...>;
};
template <template<typename...> typename Op,typename... Args>
using is_detected = typename detail::detection::detector<nonesuch,void,Args...>::value_t;
template <template<typename...> typename Op,typename... Args>
constexpr auto is_detected_v = detail::detection::detector<nonesuch,Args...>::value_t::value;
template <template<typename...> typename Op,typename... Args>
using detected_t = typename detail::detection::detector<nonesuch,Args...>::type;
template <typename Default,typename... Args>
using detected_or = typename detail::detection::detector<Default,Args...>::type;
然后可以像这样使用它:
template<typename A,typename B,typename C>
using my_is_constructible_expr = decltype(A(std::declval<B>(),std::declval<C>()));
// Trait type that has ::value
template<typename A,typename C>
using my_is_constructible = is_detected<my_is_constructible_expr,A,B,C>;
// template variable,even closer to concepts
template<typename A,typename C>
inline constexpr bool my_is_constructible_v = is_detected_v<my_is_constructible_expr,C>;