如何访问可变模板参数包成员中的内部模板typedef

How do I access an inner template typedef present in the members of a variadic template argument pack?

本文关键字:成员 内部 typedef 包成员 参数 访问 何访问      更新时间:2023-10-16

我有一些代码,对我来说似乎很明确,但gcc4.7被它卡住了:

#include <iostream>
#include <tuple>
using namespace std;
// Container for mixins
template<template<typename> class... Mixins>
struct Mix : Mixins<Mix<Mixins...>>... {
  typedef tuple<Mixins<Mix<Mixins...>>...> types;
};
// Outer layer extracts the type tuple from the argument
template<typename T>
struct InnerCombiner {
  typedef typename InnerCombiner<typename T::types>::type type;
};
// Typedef type to be a new mix of the inner mixins of the MixedMixins
template<typename... MixedMixins>
struct InnerCombiner<tuple<MixedMixins...>> {
  // This line is the problem. The compiler doesn't seem to be able to make sense
  // of the reference to the inner mixin template template classes
  typedef Mix<MixedMixins::InnerMixin...> type;
};
template<typename Mixed>
struct A {
  template<typename MixedInner>
  struct InnerMixin {
    void foo() { cout << "foo() loves you!" << endl; };
  };
};
template<typename Mixed>
struct B {
  template<typename MixedInner>
  struct InnerMixin {
    void bar() { cout << "bar() loves you!" << endl; };
  };
};
// I'm going to write out the type I expect ic to have. Oh god, it's so nasty:
// Mix<
//   A<Mix<A,B>>::InnerMixin<Mix<A<Mix<A,B>>::InnerMixin,B<Mix<A,B>>::InnerMixin>,
//   B<Mix<A,B>>::InnerMixin<Mix<A<Mix<A,B>>::InnerMixin,B<Mix<A,B>>::InnerMixin>
// >

int main() {
  InnerCombiner<Mix<A,B>>::type ic;
  ic.bar(); // Not working.
}

以这种方式访问InnerMixins有什么问题吗?当我写的时候,这似乎很合理:)

我可以通过在模板中指定InnerMixin使其在clang 3.0上工作:

typedef Mix<MixedMixins::template InnerMixin...> type;
//                       ^^^^^^^^

但它仍然在g++4.8上失败,使用

3.cpp:23:52:错误:参数包未使用"…"展开:3.cpp:23:52:注意:"MixedMixins"

类型/值不匹配,至少应该是MixedMixins::template InnerMixin...。然而GCC仍然拒绝,我也没有办法哄骗它。不幸的是,我很难证明这样的包扩展实际上是有效的。希望有更精通语法的人能回答这一点。


在更"横向"的方法中,您是否考虑过完全放弃模板模板参数?这不仅可以减轻语法的痛苦,而且您仍然可以"重新绑定"模板专业化的模板参数:

// We accept two types, a template specialization and
// a sequence of would be template parameters.
template<typename Specialization, typename T>
struct rebind;
template<
    template<typename...> class Template
    , typename... Old
    template<typename...> class Sequence
    , typename... T
>
struct rebind<Template<Old...>, Sequence<T...>> {
    using type = Template<T...>;
};
template<typename S, typename... T>
using Rebind = typename rebind<S, T...>::type;

例如,Rebind<std::vector<int>, std::tuple<double, std::allocator<double>>就是std:vector<double>。将其与parameters_of/ParametersOf实用程序相结合,以将专业化的模板参数提取到例如std::tuple中。

作为免责声明,我自己已经很久没有使用这些技术了,但我已经很感激如何将模板模板参数的痛点限制在代码的几个集中点上。