【问题标题】:What is wrong with this compile time map?这个编译时间图有什么问题?
【发布时间】:2017-09-15 04:31:18
【问题描述】:

我很难理解为什么我不能 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&lt;int V&gt; using IntMap = Map&lt;MyKey&lt;int, V&gt;;template&lt;MyEnum E&gt; using MyEnumMap = Map&lt;MyEnum, E&gt; 那样丑陋。我相信这些可以使用 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;
 }

【问题讨论】:

    标签: c++11 templates template-meta-programming


    【解决方案1】:

    Map 的前向声明期望只看到类型参数。您在特化中使用了非类型参数,这是不允许的。

    这就是编译器所抱怨的。

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

    【讨论】:

    • 我从错误消息中了解到,但我的专业是 template&lt;typename KeyType, KeyType Key, typename Value, typename... Rest&gt; struct Map&lt;KeyType, Key, Value, Rest...&gt; { 那么为什么它只期望类型?
    • @shane,我更新了我的答案。希望这更有意义。
    • 我能够通过将KeyType, Key, Value 包装在template&lt;typename KeyType, KeyType Key, typename Value&gt; struct KeyValue {}; 中来解决问题,然后Map 的特殊化是template&lt;typename KeyType, KeyType Key, typename Value, typename..Rest&gt; struct Map&lt;KeyValue&lt;KeyType, Key, Value&gt;, Rest...&gt; {};
    • @shane,您正在从专业化中删除 Rest。这是你的意图吗?
    • @shane,完美。如果您可以在帖子中添加您对Map 的意图并发布一个解释您如何解决它的答案,那就太好了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-27
    • 2014-10-21
    • 1970-01-01
    • 2016-06-21
    • 1970-01-01
    相关资源
    最近更新 更多