Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 识别STL容器_C++_Templates_C++11_Containers - Fatal编程技术网

C++ 识别STL容器

C++ 识别STL容器,c++,templates,c++11,containers,C++,Templates,C++11,Containers,通常,我想为不同的STL容器专门化一个函数。但是我不想一个接一个地专门化,因为它们中的一些共享大多数需要的接口,例如std::vector和std::deque 在我的用例中,主要有三类(向量类、集合类、地图类)。 例如,我想实现如下内容: template <class T> struct A { template <class Y, class... Z> void func( Y y , Z... z ){ //hypothetica

通常,我想为不同的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;  
};
模板
结构A{
模板
无效函数(Y,Z…Z){
//假设静态假设
static_if(T类似于vector、deque或boost::stable_vector等,具有push_back){
t、 向后推(y);
}
else static_if(T类似于set、无序_set或boost::flat_set等,它们都有位置){
t、 炮位(y);
}
else static_if(T类似于map、无序_map或boost::flat_map等,具有安放位置){
t、 炮位(y,z…);
}
}
T;
};
我认为这似乎是不可能的,但我希望有一些黑客为这种情况。
如果可以扩展到列表类型(std::list,std::forward_list,…)或boost::heap或其他类型,这也很好。然而,实现这一目标似乎太难了

这不是不可能的,只是实现起来不方便,也不琐碎。实际上,需要一个
容器

这可以通过使用来实现,以检测特定类型的
容器
是否包含满足各种STL要求的必要功能

例如,
is\u associative\u container
可以使用SFINAE检查
container
类型是否具有
键类型
映射类型
typedef,以及
值类型
std::pair
,以及实现
AssociateContainer
概念的对象的所有其他要求


无论如何,这确实需要作为一个成熟的库来实现。它的实现并不简单,如果您有一个简单的一次性需求,您可能应该寻找另一个解决方案。您最好在
迭代器
级别进行抽象。

这里是一个用于容器的粗糙类型特征库

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)... );
}
模板
结构容器特性;
模板
结构具有_emplace_back{typedef std::integral_constant emplace_back;};
模板
结构具有_位置{typedef std::integral_常量位置;};
模板
struct container_traits:has_emplace_back,has_emplace{};
//等
模板
struct container_traits:has_emplace_back,has_emplace{};
//等
模板
使用HasImplaceBack=typename容器\u traits::has\u emplace\u back;
模板
使用HasEmplace=typename容器\u traits::has\u emplace;
模板结构enum_enum{enum类类型{};};
使用uniquenum=typename enum_enum::type的模板;
模板
使用EnableIf=typename std::enable_if::type;
模板
使用DisableIf=EnableIf;
模板…>
在(容器和c、参数和…参数)中无效放置{
前进(c)炮位(前进(args)…);
}
模板…>
在(容器和c、参数和…参数)中无效放置{
标准:前进(c)。后置(标准:前进(args)…);
}

EnableIf…
技术在clang中不起作用,我没有编译它,因此可能需要一些调试来修复。

我一周前尝试了sofisticated traits,但为了更好的可读性


请看下面的例子:

不,对不起。不要这样做。Scott Meyers的有效STL中有一个完整的章节专门讨论这一点。下面是一段摘录,让您了解这一问题的严重性:

那么,假设您希望编写可用于 最常见的序列容器:vector、deque和list。清晰地 您必须编程到它们的能力的交叉点,并且 指不使用储备或容量(见第14项),因为: 不要提供它们。列表的存在还意味着您放弃了操作符[],您将自己限制在双向迭代器的功能范围内。这反过来意味着你必须远离那些 要求随机访问迭代器,包括排序、稳定排序、, 部分_排序和第n_元素(见第31项)

另一方面,您对支持向量的渴望排除了使用 向前推和向前推,vector和deque都打开了kibosh 拼接和排序的成员形式。结合上述限制,后一项禁令意味着不存在任何形式的限制 您可以在“通用序列容器”上调用的排序

这是显而易见的。如果您违反任何这些限制,您的 使用至少一个您想要编译的容器,代码将无法编译 能够使用。将要编译的代码更隐蔽

罪魁祸首是迭代器无效的不同规则, 适用于不同序列容器的指针和引用。 要编写能够正确使用vector、deque和list的代码,您需要 必须假定任何使迭代器、指针或 任何容器中的引用都会使容器中的引用无效 你正在使用。因此,您必须假设每个对insert的调用都会使所有内容无效,因为deque::insert会使所有迭代器无效, 由于缺乏调用容量的能力,vector::insert必须假定为 使所有指针和引用无效。(第1项说明deque是 独特之处在于有时使其迭代器无效,而不使其迭代器无效 指针和参考。)类似的推理得出结论 必须假设每个擦除调用都会使所有内容无效

还要吗?[是的,这一项目继续下去,继续下去,继续下去。]


目标是什么?在什么情况下向量、集合和映射是可互换的?您可以创建类型特征,并为每个类似xxx的类型指定一个函数专门化。这可以