检测类型是否为"映射"

Ron*_*Ron 4 c++ template-meta-programming

我想使用其::iterator成员类型将c ++容器解析为另一个对象.迭代器成员类型指向单个类型的对象(向量,队列等)的容器将变成类似列表的对象,并且迭代器成员类型指向的容器std::pair将变成类似于地图的对象.

我正在尝试编写一个成员函数来检测后一种容器,但它不起作用.这是我到目前为止所拥有的:

#include <tuple>
#include <iterator>
#include <type_traits>

template <typename T>
struct is_pair : std::false_type { };

template <typename T, typename U>
struct is_pair<std::pair<T, U>> : std::true_type { };

template <typename T>
constexpr bool is_pair_v = is_pair<T>::value;

template <typename...>
struct is_mapping : std::false_type { };

template <typename Container>
struct is_mapping<Container, std::enable_if_t<
    is_pair_v<std::iterator_traits<typename Container::iterator>::value_type>
>> : std::true_type { };

template <typename T>
constexpr bool is_mapping_v = is_mapping<T>::value;

#include <map>
#include <vector>
#include <iostream>

int main() {
    std::cout << "is_pair:" << std::endl;
    std::cout << "Map:    " << is_pair_v<std::iterator_traits<std::map<int, int>::iterator>::value_type> << std::endl;
    std::cout << "Vector: " << is_pair_v<std::iterator_traits<std::vector<int>::iterator>::value_type>   << std::endl;
    std::cout << std::endl;
    std::cout << "is_mapping:" << std::endl;
    std::cout << "Map:    " << is_mapping_v<std::map<int, int>> << std::endl;
    std::cout << "Vector: " << is_mapping_v<std::vector<int>>   << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

出于某种原因,is_mapping_v始终为false并且代码会导致此输出:

$ g++ -std=c++14 temp.cc && ./a.out
is_pair:
Map:    1
Vector: 0

is_mapping:    
Map:    0
Vector: 0
Run Code Online (Sandbox Code Playgroud)

我的代码出了什么问题?


注意:这不是检查类型是否为地图的副本.该问题的答案使用::key_type::mapped_type成员来检测地图(对于诸如此类的类失败std::multimap).我也明确地使用了迭代器std::pair在我的代码中稍后指向的事实,因此检查它会更有意义.

Pas*_* By 6

is_pair_v<std::iterator_traits<typename Container::iterator>::value_type>
Run Code Online (Sandbox Code Playgroud)

应该

is_pair_v<typename std::iterator_traits<typename Container::iterator>::value_type>
Run Code Online (Sandbox Code Playgroud)

因为value_type是一种类型.如果没有typename,它将被解析为值并失败enable_if,从而回退到主模板.

您的测试main产生正确值的原因是因为那里的模板已经实例化,并且没有歧义,无论value_type是类型还是值.

第二个错误是您的主要模板

template<typename...>
Run Code Online (Sandbox Code Playgroud)

应该

template<typename, typename = void>
Run Code Online (Sandbox Code Playgroud)

否则,is_mapping<T>永远不会是两个参数的专门化,因为参数计数不匹配.

生活