很多时候,我想专门针对不同的STL容器使用一个函数.但是我不想一个接一个地专门化,因为它们中的一些共享大多数所需的接口,例如std :: vector和std :: deque.
在我的用例中,大多有三个类别(类似矢量,类似集合,类似地图).
例如,我想实现类似的东西,
template <class T>
struct A {
template <class Y, class... Z>
void func( Y y , Z... z ){
//hypothetical static_if
static_if ( T is similar to vector, deque, or boost::stable_vector etc which have push_back ) {
t.push_back(y);
}
else static_if ( T is similar to set, unordered_set or boost::flat_set etc which have emplace) {
t.emplace(y);
}
else static_if ( T is similar to map, unordered_map or boost::flat_map etc which has emplace) {
t.emplace(y, z...);
}
}
T t;
};
我认为这似乎不可能,但我希望这种情况有某种破解.
如果它可以扩展到列表类型(std :: list,std :: forward_list,…)或boost :: heap或其他也是好的.然而,实现目标似乎太难了.
解决方法:
这是容器的粗略类型特征库.
template<typename Container>
struct container_traits;
template<bool b=true>
struct has_emplace_back { typedef std::integral_constant<bool, b> emplace_back; };
template<bool b=true>
struct has_emplace { typedef std::integral_constant<bool, b> emplace; };
template<typename T, typename A>
struct container_traits< std::vector<T,A> > : has_emplace_back<>, has_emplace<> {};
// etc
template<typename T, typename A>
struct container_traits< std::set<T,A> > : has_emplace_back<false>, has_emplace<> {};
// etc
template<typename T>
using HasEmplaceBack = typename container_traits<T>::has_emplace_back;
template<typename T>
using HasEmplace = typename container_traits<T>::has_emplace;
template<int> struct enum_enum { enum class type {}; };
template<int index> using UniqueEnum = typename enum_enum<index>::type;
template<bool b, int index=1>
using EnableIf = typename std::enable_if< UniqueEnum<index> >::type;
template<bool b, int index=1>
using DisableIf = EnableIf< b, -index >;
template<typename Container, typename... Args, EnableIf< HasEmplace<Container>::value && !HasEmplaceBack<Container>::value, 1 >... >
void emplace_in( Container&& c, Args&&... args ) {
std::forward<Container>(c).emplace( std::forward<Args>(args)... );
}
template<typename Container, typename... Args, EnableIf< HasEmplaceBack<Container>::value, 2 >... >
void emplace_in( Container&& c, Args&&... args ) {
std::forward<Container>(c).emplace_back( std::forward<Args>(args)... );
}
EnableIf<> …技术在clang中不起作用,我没有编译它所以它可能需要一些调试来修复.