4

私には明白に見えるコードがいくつかありますが、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にアクセスすることに何か問題がありますか?私がそれを書いたとき、それはかなり合理的であるように見えました:)

4

2 に答える 2

4

InnerMixinテンプレートを指定することで、clang3.0動作させることができます。

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

しかし、それでもg++4.8では失敗します。

3.cpp:23:52:エラー:パラメータパックが「...」で展開されていません:
3.cpp:23:52:注:'MixedMixins'
于 2012-03-20T08:04:19.780 に答える
1

タイプ/値の不一致があります。これは少なくともである必要があります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

免責事項として、私は長い間これらの手法を使用していませんが、テンプレートテンプレートパラメーターの問題点をコードのいくつかの集中化されたスポットに制限する方法をすでに理解しています。

于 2012-03-20T08:13:03.053 に答える