Как я могу получить доступ к внутреннему шаблону typedef, присутствующему в членах пакета аргументов variadic шаблона? - PullRequest
4 голосов
/ 20 марта 2012

У меня есть некоторый код, который мне кажется однозначным, но 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? Казалось, довольно разумно, когда я написал это:

Ответы [ 2 ]

4 голосов
/ 20 марта 2012

Я могу заставить его работать на clang 3.0 , указав InnerMix в шаблоне:

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

, но все равно происходит сбой на g ++ 4.8, с

3.cpp:23:52: error: parameter packs not expanded with ‘...’:
3.cpp:23:52: note:         ‘MixedMixins’
1 голос
/ 20 марта 2012

Существует несоответствие типа / значения, по крайней мере, оно должно быть 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.

. В качестве заявления об отказе я сам долгое время не использовал эти методы, но яЯ уже оценил, как я могу ограничить болевые точки параметров шаблона шаблона несколькими централизованными точками моего кода.

...