从参数包中删除最后一个参数

时间:2014-08-12 20:22:57

标签: c++ templates c++11 variadic-templates

今天,在第100次使用相同的模板时,我想到了引入简单替换的想法。

而不是

 QHash<int,QHash<int,QHash<int,int> > >

现在应该是:

 MultiKeyHash<int,int,int,int>

(不要与QT&#39的QMultiHash类混淆)。

前三个参数是键的类型,最后一个参数是值的类型。

 MultiKeyHash<TKey1,TKey2,....,TKeyN,TValue>

我目前的实现如下:

template <typename... Args>
struct MultiKeyHash;

template <typename TKey1, typename... Args>
struct MultiKeyHash<TKey1, Args...> : QHash<TKey1,MultiKeyHash<Args...> > {

    typedef typename MultiKeyHash<Args...>::ValueType ValueType;
    const ValueType& value(const TKey1 &key1, const Args_Without_Last&... args) const {
          return operator[](key1).value(args...);
    }
};

template <typename TKeyN, typename TValue>
struct MultiKeyHash<TKeyN,TValue> : QHash<TKeyN,TValue> {
    typedef TValue ValueType;
};

一切都按预期工作,直到我想添加&#34;值&#34;方法。我当然不能使用&#34; Args&#34;作为第二个参数的类型(-pack)。我是否必须制作它的功能模板,或者有办法吗?

我如何定义&#34;值&#34;方法,以便能够像:

一样调用它
value(key1,key2,...,keyn)

2 个答案:

答案 0 :(得分:3)

这是MultiHashKey的工作版本。它使用QHash的虚拟实现进行测试。

#include <iostream>

// Dummy implementation of QHash for testing purposes.
template <typename TKey, typename TValue>
struct QHash
{
   void insert(const TKey& key, const TValue& val) {this->val = val;}
   const TValue& value(const TKey& key) const { return val; }
   TValue val;
};

template <typename... Args> struct MultiKeyHash;

template <typename TKey, typename... Args>
struct MultiKeyHash<TKey, Args...> : QHash<TKey, MultiKeyHash<Args...>>
{
   typedef TKey KeyType;
   typedef typename MultiKeyHash<Args...>::ValueType ValueType;
   typedef QHash<KeyType, MultiKeyHash<Args...>> QHashType;

   using QHashType::insert;
   using QHashType::value;

   MultiKeyHash() {}

   MultiKeyHash(const TKey &key, const Args&... args)
   {
      this->insert(key, MultiKeyHash<Args...>(args...));
   }

   void insert(const TKey &key, const Args&... args)
   {
      MultiKeyHash<Args...> val(args...);
      this->insert(key, val);
   }
   template <typename TKey1, typename ... Args1>
   const ValueType& value(const TKey1 &key1, const Args1&... args1) const
   {
      MultiKeyHash<Args...> const& val = this->value(key1);
      return val.value(args1...);
   }
};

template <typename TKey, typename TValue>
struct MultiKeyHash<TKey, TValue> : QHash<TKey, TValue> 
{
   typedef TKey KeyType;
   typedef TValue ValueType;
   typedef QHash<KeyType, ValueType> QHashType;

   MultiKeyHash() {}

   MultiKeyHash(const TKey &key, const TValue& val)
   {
      this->insert(key, val);
   }
};

void test1()
{
   MultiKeyHash<int, double> hash;
   hash.insert(10, 200.5);
   double v = hash.value(10);
   std::cout << "Value: " << v << std::endl;
}

void test3()
{
   MultiKeyHash<int, int, int, double> hash;
   hash.insert(10, 10, 10, 20.5);
   double v = hash.value(10, 10, 10);
   std::cout << "Value: " << v << std::endl;
}

int main()
{
   test1();
   test3();
   return 0;
};

运行程序的输出:

Value: 200.5
Value: 20.5

答案 1 :(得分:2)

如果你使value成为一个可变参数模板,你可以以更糟糕的错误消息为代价完全避免这个问题,因为转换将发生在函数内而不是在调用点:

template <typename First, typename...Remainder>
const ValueType& value(First&& first, Remainder&&... rest) const {
    return value(std::forward<First>(first)).value(std::forward<Remainder>(rest)...);
}