在模板元编程中,有一个窍门:
template <typename T>
struct my_struct {};
template <typename... T1, typename... Ts>
struct my_struct <std::tuple<T1, Ts...>>
{
// Tuple is "unpacked"
// I can freely work on 'T1' & 'Ts' types (through recursion) in this scope.
using type = T1;
};
我希望成员函数(尤其是构造函数)存在类似的技巧:
template <typename T>
struct my_struct {};
// specialisation for case when type 'T' has 'T(U1, Us...)' ctor.
template <typename T, typename U1, typename... Us>
struct my_struct <
decltype(T::T(
std::declval<U1>(),
std::declval<Us>()...
))
>
{
using type = U1;
};
不幸的是,这会导致错误:
模板参数“ U1”和参数包“ Us”未在类模板“ my_struct”的模板参数列表中使用或无法推导出来
有没有办法获取T的ctor参数的类型?
我需要上面的内容,因为我有一个函数func<T>()
,对于类型T
具有T(std::initializer_list</* ??? */>)
构造函数的情况,必须对其进行“专门化”(/“重载”)。
template<typename T>
struct get_init_list_type_from_T_ctor
{
// magic happens here
};
template<typename T>
using has_init_list_ctor = std::enable_if_t<
std::is_constructible_v<
T,
std::initializer_list<
typename get_init_list_type_from_T_ctor<T>::type
>
>
>;
// version for T with initialization list ctor
template<
typename T,
typename = std::enable_if_t<
std::is_detected_v<has_init_list_ctor, T>
>
>
void func() {
//...
}
// version for T without initialization list ctor
template<
typename T,
typename = std::enable_if_t<
!std::is_detected_v<has_init_list_ctor, T>
>
>
void func() {
//...
}
答案 0 :(得分:0)
不可能在C ++中强制执行特定的构造函数签名。
但是,如果初始化列表的类型是固定的,您仍然可以通过使用必需的参数调用构造函数来利用SFINAE:
template <typename T, typename U>
struct has_init_list_ctor
: std::is_constructible<T, std::initializer_list<U>>
{
};
template <typename T, typename U>
inline constexpr bool has_init_list_ctor_v = has_init_list_ctor<T, U>::value;
如果您不知道初始化列表的类型,则此方法将无效。我们必须等待Reflection TS。如果真是这样,我想不出这怎么可能有用。