c++ - 具有可变参数的元组内容的部分特化

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

目前,我正在尝试让一些代码对不同的类型做出不同的 react 。这不是确切的代码,但它传达了信息。

template<class A, class B>
struct alpha {
  enum { value = 0 };
};

template<class T, class... Args>
struct alpha<std::tuple<Args...>, T> {
  enum { value = 1 };
};

// This gets ignored
template<class T, class... Args>
struct alpha<std::tuple<Args..., std::vector<T> >, T> {
  enum { value = 2 };
};

// This gets ignored
template<class T, class... Args>
struct alpha<std::tuple<Args..., T>, T> {
  enum { value = 3 };
};

template<class T, class... Args>
struct alpha<T, std::tuple<Args...> > {
  enum { value = 4 };
};

template<class... LArgs, class... RArgs>
struct alpha<std::tuple<LArgs...>, std::tuple<RArgs...> > {
  enum { value = 5 };
};

int main(int argc, char* argv[]) {
  std::cout << alpha<std::tuple<int, double>, double>::value << std::endl; // prints 1
  return 0;
}

我已经尝试了比这段代码更多的尝试,但到目前为止没有任何效果,我遇到了一个在非命名空间范围内显式特化的问题。作为引用,我正在研究 gcc 4.6(oneiric 服务器附带的那个),我相信它具有完整的可变参数模板支持。如果实现能够检测参数包的最后一个参数以及其他类型,我不在乎它变得多么丑陋。有什么建议吗?

编辑: 我想根据答案分享我使用的解决方案(这是一个例子)。

template<typename T> struct tuple_last;

template<typename T, typename U, typename... Args>
struct tuple_last<std::tuple<T,U,Args...>> {
  typedef typename tuple_last<std::tuple<U,Args...>>::type type;
};

template<typename T>
struct tuple_last<std::tuple<T>> {
  typedef T type;
};

namespace details {
// default case:
template<class T, class U>
struct alpha_impl {
enum { value = 1 };
};

template<class T>
struct alpha_impl<T, T> {
enum { value = 101 };
};

template<class T>
struct alpha_impl<T, std::vector<T>> {
enum { value = 102 };
};

// and so on.
}

template<class T, class... Args>
struct alpha<std::tuple<Args...>, T>
  : details::alpha_impl<T, tuple_last<std::tuple<Args...>>;

最佳答案

如果使用 clang 编译, 它有帮助地报告 (2) 和 (3) 不可用。您希望被选中的(3)的警告如下:

warning: class template partial specialization contains a template parameter that can not be deduced; this partial specialization will never be used

struct alpha<std::tuple<Args..., T>, T> {
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

note: non-deducible template parameter 'Args'

template<class T, class... Args>
                           ^

为什么是Args不能扣除? C++0x FDIS 在 §14.8.2.5/9 中声明:

If the template argument list of [a type that is specified in terms of template parameters] contains a pack expansion that is not the last template argument, the entire template argument list is a non-deduced context.

在您的专业中,类型 std::tuple<Args..., T>是根据模板参数指定的类型 ArgsT .它包含一个包扩展( Args... ),但该包扩展不是最后一个模板参数( T 是最后一个模板参数)。因此,tuple 的整个模板参数列表(<Args..., T> 的整体)是一个非推导上下文。

std::tuple 的参数列表是模板特化参数列表中唯一一个 Args 的地方出现;因为它不能从那里推导出来,所以它根本不能推导出来,并且永远不会使用特化。

马修 M. provides a clever workaround in his answer .

关于c++ - 具有可变参数的元组内容的部分特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6757691/

相关文章:

c++ - 将 unique_ptr 的映射 move 到 unique_ptr 的常量映射中

c++ - 捕获模板化异常时的编译器错误

c++ - std::bind std::shared_ptr 参数不会增加 use_count

c++ - 使用模板化方法进行类型删除

c++ - 按节点计算单链表中的出现次数

c++ - 变量是大小为 1 的数组吗?

c++ - QThread 和 QTcpSocket

c++ - Q_OBJECT 链接器错误!

c++ - 在没有宏的情况下在 C++98 中创建类型列表时遇到问题

c++ - 模板类的对象创建包装器