爲此編寫一個真正通用的解決方案很困難。檢查任意類型T
與std::vector
或std::array
的問題是後者不是類,它們是類模板。更糟糕的是,std::array
是一個帶有非模板參數的類模板,所以你甚至不能擁有一個參數包,它可以容納std::vector
和std::array
。
你可以通過在類型中顯式包裝非類型參數來解決這個問題,但它會變得很難看,速度很快。
這是我提出的一個解決方案,它將默認支持任何沒有非模板參數的類或模板類。通過添加包裝類型來將非類型參數映射到類型參數,可以支持具有非類型模板參數的模板類。
namespace detail{
//checks if two types are instantiations of the same class template
template<typename T, typename U> struct same_template_as: std::false_type {};
template<template<typename...> class X, typename... Y, typename... Z>
struct same_template_as<X<Y...>, X<Z...>> : std::true_type {};
//this will be used to wrap template classes with non-type args
template <typename T>
struct wrapImpl { using type = T; };
//a wrapper for std::array
template <typename T, typename N> struct ArrayWrapper;
template <typename T, std::size_t N>
struct ArrayWrapper<T, std::integral_constant<std::size_t, N>> {
using type = std::array<T,N>;
};
//maps std::array to the ArrayWrapper
template <typename T, std::size_t N>
struct wrapImpl<std::array<T,N>> {
using type = ArrayWrapper<T,std::integral_constant<std::size_t,N>>;
};
template <typename T>
using wrap = typename wrapImpl<typename std::decay<T>::type>::type;
//checks if a type is the same is one of the types in TList,
//or is an instantiation of the same template as a type in TempTList
//default case for when this is false
template <typename T, typename TList, typename TempTList>
struct one_of {
using type = std::false_type;
};
//still types in the first list to check, but the first one doesn't match
template <typename T, typename First, typename... Ts, typename TempTList>
struct one_of<T, std::tuple<First, Ts...>, TempTList> {
using type = typename one_of<T, std::tuple<Ts...>, TempTList>::type;
};
//type matches one in first list, return true
template <typename T, typename... Ts, typename TempTList>
struct one_of<T, std::tuple<T, Ts...>, TempTList> {
using type = std::true_type;
};
//first list finished, check second list
template <typename T, typename FirstTemp, typename... TempTs>
struct one_of<T, std::tuple<>, std::tuple<FirstTemp, TempTs...>> {
//check if T is an instantiation of the same template as first in the list
using type =
typename std::conditional<same_template_as<wrap<FirstTemp>, T>::value,
std::true_type,
typename one_of<T, std::tuple<>, std::tuple<TempTs...>>::type>::type;
};
}
//top level usage
template <typename T, typename... Ts>
using one_of = typename detail::one_of<detail::wrap<T>,Ts...>::type;
struct Foo{};
struct Bar{};
template <class Type>
auto operator<< (std::ostream& stream, const Type subject)
//is Type one of Foo or Bar, or an instantiation of std::vector or std::array
-> typename std::enable_if<
one_of<Type, std::tuple<Foo,Bar>, std::tuple<std::vector<int>,std::array<int,0>>
>::value, std::ostream&>::type
{
stream << "whatever, derived from subject\n";
return stream;
}
請不要使用這個,這太可怕了。的[C++模板,僅接受某些類型](
Live Demo
可能重複的http://計算器。COM /問題/ 874298/C的模板,也就是說,接受只,某些類型) –
的問題是,我想包括類型,如性病::陣列,性病::陣列,性病::陣列, ......這就是一個無窮級數不同類型的....不知道是否有一種方法可以做到這一點.. –
我仍然無法找到答案,如何防止實例化編譯器從我的模板函數,當我使用cout << int(5)。當斷言失敗時,static_assert或BOOST_STATIC_ASSERT將生成一個編譯錯誤,而不是忽略我的模板。 –