在模板化函数中,其中一个参数是T
类型的标准库容器,我可以轻松静态断言T
是一个有序容器吗?
是否有更优雅的方法来执行此操作,而不是执行特定于类型的操作,例如测试是否存在hash_function()
函数以区分std::map
和std::unordered_map
?
答案 0 :(得分:3)
另一个简单的问题:
template <template <typename...> class Container>
struct is_ordered : std::false_type {};
template <> struct is_ordered<std::map> : std::true_type {};
template <> struct is_ordered<std::set> : std::true_type {};
template <> struct is_ordered<std::multimap> : std::true_type {};
template <> struct is_ordered<std::multiset> : std::true_type {};
然后只需static_assert(is_ordered<Container>::value, "error")
即可使用它。扩展到自定义容器也很容易:只需添加如上所示的行。
如果您不想在呼叫站点使用模板模板,您可以始终将其包装为ala:
template <typename T> struct is_ordered_2 : std::false_type {};
template <template <typename...> class Container, typename... Ts>
struct is_ordered_2<Container<Ts...>> : is_ordered<Container> {};
然后你可以使用它。
答案 1 :(得分:1)
这种方法非常简单:
// default result
template<class T>constexpr bool IsOrdered(const T&) {return false;}
// now enumerate the ordered standard library types of interest:
template<class K, class T, class C, class A>
constexpr bool IsOrdered(const std::map<K,T,C,A>&) {return true;}
// ...remaining types...
答案 2 :(得分:0)
例如,如果您只关注禁止使用std::unordered_map
和std::unordered_set
这样的特定类,则可以使用与static_assert
一致的类型特征:
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
template <typename Container, typename T>
void func(Container<T> &c)
{
// make sure that the provided container isn't a type we don't want!
static_assert(!std::is_same<Container<T>, std::unordered_map<T>>::value);
static_assert(!std::is_same<Container<T>, std::unordered_set<T>>::value);
}
我不确定这是否符合原始问题的“特定类型”。您根本没有查看禁止类的内部(例如查找hash_function()
,但此方法需要您枚举您不想使用的容器。
答案 3 :(得分:0)
你可以(强调可以,因为我不认为它是标准的)做这样的事情:
template <typename T>
struct has_typedef_key_compare
{
// Types "yes" and "no" are guaranteed to have different sizes,
// specifically sizeof(yes) == 1 and sizeof(no) == 2.
typedef char yes[1];
typedef char no[2];
template <typename C>
static yes& test(typename C::key_compare*);
template <typename>
static no& test(...);
// If the "sizeof" of the result of calling test<T>(0) would be equal to sizeof(yes),
// the first overload worked and T has a nested type named foobar.
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
template <typename T>
struct is_sorted_container
{
static const bool value;
};
template <typename T>
const bool is_sorted_container<T>::value = has_typedef_key_compare<T>::value;
基本原理是所有已排序的stl容器(我看过)都有一个key_compare函数。当然,这不是标准。这不会涵盖非stl类型。总而言之,我不喜欢它,但我认为我会把它作为一个有趣的替代品发布。
stl函数(如std :: upper_bound)如何解决这个问题是将排序迭代器的限制放在注释中,让最终用户弄明白。