2017-09-15 77 views
0

我挣扎明白,为什么我不能的typedef这个地图,编译器会抱怨这个编译时间图有什么问题?

main.cpp:14:41: error: type/value mismatch at argument 1 in template 
parameter list for 'template<class ...> struct Map' 
struct Map<KeyType, Key, Value, Rest...> { 
            ^
main.cpp:14:41: note: expected a type, got 'Key' 
main.cpp:24:23: error: type/value mismatch at argument 1 in template 
parameter list for 'template<class ...> struct Map' 
typedef Map<int, 1, A> map; 

这里是

#include <type_traits> 
#include <iostream> 

template<typename...> 
struct Map; 

template<typename KeyType> 
struct Map<KeyType> { 
    template<KeyType NotFound> 
    struct get { typedef std::false_type val; }; 
}; 

template<typename KeyType, KeyType Key, typename Value, typename... Rest> 
struct Map<KeyType, Key, Value, Rest...> { 
    template<KeyType Get> 
    struct get { 
     typedef std::conditional<Get == Key, Value, typename Map<KeyType, Rest...>::template get<Get>::val> val; 
    }; 
}; 

struct A { static constexpr int value = 1; }; 
struct B { static constexpr int value = 2; }; 

typedef Map<int, 1, A> map; 

int main() { 
    std::cout << map::get<1>::val::value << std::endl; 
    //std::cout << map::get<2>::val::value << std::endl; 
    //std::cout << map::get<3>::val::value << std::endl; 
} 

看来,在某种程度上正在采取在地图上的typedef的第一个关键的代码作为关键类型,我不确定这是怎么发生的。

编辑

我来到了一个解决方案,我们的目标是有一些恒定值的类型编译时间图,这样我就可以在编译时映射到枚举类型。我能够通过将Key包装到一个类型中,并将KeyType作为第一个模板参数传递给地图来解决问题。一些样板类型定义使它不像template<int V> using IntMap = Map<MyKey<int, V>;template<MyEnum E> using MyEnumMap = Map<MyEnum, E>那样难看。我相信这些可以使用C++ 17自动模板更清洁。请给出意见。

#include <type_traits> 
#include <iostream> 

template<typename KeyType, KeyType Key> 
struct KeyValue {}; 

struct KeyNotFound {}; 

template<typename...> 
struct Map; 

template<typename KeyType> 
struct Map<KeyType> { 
    template<KeyType Key> 
    struct get { typedef KeyNotFound type; }; 
}; 

template<typename KeyType, KeyType Key, typename Value, typename... Rest> 
struct Map<KeyType, KeyValue<KeyType, Key>, Value, Rest...> { 
    template<KeyType Get> 
    struct get { 
     typedef typename std::conditional<Get == Key, Value, typename Map<KeyType, Rest...>::template get<Get>::type>::type type; 
    }; 
}; 

struct A { static constexpr int value = 1; }; 
struct B { static constexpr int value = 2; }; 


typedef Map<int, 
    KeyValue<int, 1>, A, 
    KeyValue<int, 2>, B> map; 

int main() { 
    std::cout << map::get<1>::type::value << std::endl; 
    //std::cout << map::get<2>::val::value << std::endl; 
    //std::cout << map::get<3>::type::value << std::endl; 
} 

回答

0

Map的前向声明预计只能看到类型参数。您正在专门化中使用非类型参数,这是不允许的。

这就是编译器所抱怨的。

我无法提出解决方案,因为我不知道你想用混合的类型和非类型参数来完成什么。

+0

据我所知,从错误消息,但我的专业是'模板结构Map {'so为什么只是期待类型? – shane

+0

@shane,我更新了我的答案。希望这更有意义。 –

+0

我能够通过将'KeyType,Key,Value'封装在'template struct KeyValue {};''然后'Map'专用为'template 来解决问题, KeyType Key,typename Value,typename..Rest> struct Map ,Rest ...> {};' – shane