【问题标题】:How do I access an inner template typedef present in the members of a variadic template argument pack?如何访问可变参数模板参数包成员中存在的内部模板 typedef?
【发布时间】:2012-03-20 07:25:36
【问题描述】:

我有一些对我来说似乎很明确的代码,但 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 有什么问题吗?当我写它时,它似乎很合理:)

【问题讨论】:

  • 与您的问题无关,但这意味着InnerCombiner&lt;Mix&lt;A, B&gt;::types&gt;::type,或者InnerCombiner 特化意味着匹配Mix&lt;MixedMixins...&gt; 或通用模板模板参数而不是std::tuple。跨度>
  • 我认为这是正确的,因为 T 旨在成为某种 Mix<...>,并且 mix 具有 ::types,因此未专门化的 InnerCombiner 提取类型以应用于部分专业化的 InnerCombiner。那会奏效吗?不过你是对的,匹配 Mix<...> 会更优雅。我想我仍然会遇到同样的问题。
  • PS 253 答案,没有问题?!你从来不被难倒吗? :)
  • 是的,这行得通。当程序中没有任何成员时,发现一个 int 成员的 GCC 错误消息让我难过(说到)。
  • @LucDanton 是的,我也注意到了。我认为这可能是编译器在出错后尝试继续的策略,这样它可以提供更多错误,您可以一次修复它们。

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


【解决方案1】:

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

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

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

3.cpp:23:52: 错误: 参数包没有用‘...’扩展: 3.cpp:23:52: 注意:‘MixedMixins’

【讨论】:

  • 该死。无论如何感谢您的回答。您是否碰巧知道解释为什么有效的标准规定?
  • @rodarmor This question 它的答案有参考。
  • @Luc 不幸的是,标准目前不需要“::template”作为模板模板参数。上周我发送了一份关于该问题的问题报告,我希望将其添加到下一个问题列表中。
【解决方案2】:

类型/值不匹配,至少应该是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&lt;std::vector&lt;int&gt;, std::tuple&lt;double, std::allocator&lt;double&gt;&gt;std:vector&lt;double&gt;。将其与parameters_of/ParametersOf 实用程序结合起来,将专业化的模板参数提取到例如一个std::tuple

作为免责声明,我自己并没有长时间使用这些技术,但我已经很欣赏如何将模板模板参数的痛点限制在我的代码的几个集中点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-29
    • 1970-01-01
    相关资源
    最近更新 更多