【问题标题】:C++11: Implementing a Selector between std::array and std::unordered_map according to item countC++11:根据项目计数在 std::array 和 std::unordered_map 之间实现选择器
【发布时间】:2016-02-08 21:57:23
【问题描述】:

我正在尝试创建一个映射类,它会根据可能的值范围自动选择正确的实现。如果取值范围最大为 256,则使用std::array,否则使用std::unordered_map

template<typename KeyType, typename ValType>
class MapImpl : public std::unordered_map<KeyType,ValType>
{
  void foo() { std::cout << "Map foo" << std::endl; }
};

template<typename ValType, std::size_t Size>
class ArrImpl : public std::array<ValType,Size>
{
public:
  void foo() { std::cout << "Arr foo" << std::endl; }
};

template<typename KeyType, typename ValType,
         KeyType min_value = boost::integer_traits<KeyType>::const_min,
         KeyType max_value = boost::integer_traits<KeyType>::const_max>
class MappingSelector
{
public:
  void bar() { map.foo(); }
private:
  typedef std::conditional<(max_value-min_value < 256),
                           ArrImpl<ValType,max_value-min_value+1>,
                           MapImpl<KeyType,ValType>
                          > MappingType;
  MappingType map;
};

到目前为止一切顺利(?) 然后我实例化它:

MappingSelector<unsigned char, double> ms;
ms.bar();

但是,编译器似乎不喜欢这样,并告诉我我的MappingType 没有名为foo 的成员。

【问题讨论】:

  • 你定义foo了吗?
  • 是的。 foo 是为两个 Impl 类定义的
  • 我也不能使用size()at()operator[],即使这两种类型都有。

标签: c++ c++11 metaprogramming


【解决方案1】:

std::conditional 不直接定义结果类型,但它定义了一个结构,该结构具有对应类型的typedef type

这意味着你必须限定特定的类型,所以你的 typedef 应该是

typedef std::conditional<(max_value-min_value < 256),
ArrImpl<ValType,max_value-min_value+1>,
MapImpl<KeyType,ValType>
> MappingType;
typename MappingType::type map;
    ^ requires typename for unambiguation
                       ^ ::type is the real typedef

或者你可以直接输入定义MappingType,用::type限定它,同样的结果。实际上,由于您使用的是 C++11,因此您也可以使用using,例如:

using MappingType = typename std::conditional<(max_value-min_value < 256),
ArrImpl<ValType,max_value-min_value+1>,
MapImpl<KeyType,ValType>
>::type;

MappingType map;

【讨论】:

    【解决方案2】:

    问题可能出在

    typedef std::conditional<(max_value-min_value < 256),
                           ArrImpl<ValType,max_value-min_value+1>,
                           MapImpl<KeyType,ValType>
                          > MappingType;
    

    你可能的意思

    typedef typename std::conditional<(max_value-min_value < 256),
                           ArrImpl<ValType,max_value-min_value+1>,
                           MapImpl<KeyType,ValType>
                          >::type MappingType;
    

    您实际上并没有typedef 这里是您所指的类型之一(IIUC);相当。你typedefed 类型的“if 语句”。


    请参阅here 示例,了解如何使用此构造。

    【讨论】:

      【解决方案3】:

      std::conditional 是一个特征类,它将所选类型公开为::type。所以你需要这样做:

        typedef typename std::conditional<...>::type MappingType;
      

      如果你有 C++14,你可以通过使用别名模板来简化这个:

        typedef std::conditional_t<...> MappingType;
      

      【讨论】:

        猜你喜欢
        • 2011-04-23
        • 1970-01-01
        • 1970-01-01
        • 2017-10-13
        • 1970-01-01
        • 2012-05-23
        • 1970-01-01
        • 1970-01-01
        • 2016-05-12
        相关资源
        最近更新 更多