Ограничить шаблон функции вариации, чтобы принимать только вариации одного шаблона шаблона вложенного класса шаблона вариады? - PullRequest
2 голосов
/ 11 декабря 2010

У меня есть шаблон класса variadic, который имеет вложенный шаблон класса variadic. Шаблон внешнего класса имеет шаблон функции, который принимает любое количество аргументов и возвращает объект типа inner. Моя проблема заключается в создании совершенно отдельной функции, которая будет принимать любое количество любых вариаций этих внутренних типов (и только внутренних типов), независимо от варианта внешнего типа, и в то же время обеспечивать, чтобы принятые типы для функции были вложенными членами только этот шаблон внешнего класса. Не уверен, что я объяснил это адекватно ... Вот по сути то, с чем я работаю:

template<typename... ArgsOuter> class Outer {
    typedef Outer<ArgsOuter...> outer_t;

    template<typename... ArgsInner> class Inner {
        //static const outer_t* outer;
        typedef outer_t outer;

        Inner(const ArgsInner&... args_inner) {
            //do stuff
        }
    };

    /*
      What's passed in here will be related to and will be a subset of
      the types used to define the Outer class, but I'm not really
      concerned about checking what's being passed in right now.
    */
    template<typename... ArgsFunc>
    make_inner(ArgsFunc... args_func) {
        return Inner<ArgsFunc...> (args_func...);
    }
};

struct ThingA : Outer<int, int, float> {
};

struct ThingB : Outer<int, string, int> {
};

struct ThingC : Outer<string, string, int, int> {
};

//struct ThingN : Outer<random types...> {}

//...meanwhile, over at main...

ThingA tA;
ThingB tB;
ThingC tC;

auto tA_inner = tA.make_inner(1, 1.1);
auto tB_inner = tB.make_inner(2, "foo");
auto tC_inner = tC.make_inner("bar", 2, "foobar");

//mystery_func() is the function I'm not sure how to define.
auto meatloaf = mystery_func(tA_inner, tB_inner, tC_inner);

У кого-нибудь есть для этого решение с функцией SFINAE или с переменным шаблоном (или другое)?

Ответы [ 2 ]

2 голосов
/ 11 декабря 2010

Я думаю, что это на самом деле невозможно. То, что вы, кажется, хотите, это способность делать что-то вроде этого:

template < typename ... Args1, typename ... Args2, typename ... Args3>
?? mystery_func(Inner<Args1...>,Inner<Args2...>,Inner<Args3...>);

Я не думаю, что вы можете сделать это. Если можешь, то есть твой ответ.

Поскольку я сомневаюсь, что вы можете сделать это, вместо этого вам нужно просто взять три разных типа и затем использовать SFINAE, чтобы проверить, что они Inner <> s, что было бы так же просто, как использовать базовую метафункцию is_a. :

template < typename T > is_inner : boost::mpl::false_ {};
template < typename ... Pack > is_inner< Inner<Pack...> > : boost::mpl::true_ {};
1 голос
/ 15 декабря 2010

Ну, я не собирался отвечать на свой вопрос, но я думаю, что за последние несколько дней я ударился головой о стену достаточно, чтобы понять это ... и, конечно, узнал кое-что новое.кстати (нареканий нет).Это немного гадкий утёнок (метафункции черт типа SFINAE + шаблоны функций variadic), но я выполнил несколько простых тестов, и, похоже, он работает как ожидалось.типы, передаваемые в любые вариации Inner для любых вариаций Outer.Я думаю, что это делает то, что я искал, по крайней мере, так кажется.

Мое понимание того, как все это работает, заключается в следующем, пожалуйста, исправьте при необходимости:

Серия Inner объекты передаются внутрь. Каждый Inner объект имеет typedef, ссылающийся на его тип 'Outer.Мы удаляем один объект Inner из пакета параметров и проверяем typedef, ссылаясь на его тип 'Outer, чтобы убедиться, что он соответствует ожидаемому типу Outer.Если он совпадает, то мы берем пакет параметров, использованный в первом переданном объекте Inner, и передаем пакет вместе с шаблоном Inner, на который мы ссылаемся через определение типа Outer, на которое ссылается первый Inner.Затем мы проверяем эти два Inner друг против друга, чтобы убедиться, что они одинаковы.Если они есть, то это конкретное создание экземпляра шаблона функции включено.

Сам шаблон функции variadic просто вызывает себя рекурсивно, так что все объекты в пакете параметров имеют те же проверки на них, пока у нас не закончатся аргументы, который вызывает пустую версию функции.Наконец, каждая рекурсия вызывает (в данном случае) функцию, которая объединяет объекты в список.

В одном я не уверен, что компилятор оптимизирует все эти вызовы make_listкоторые возвращаются в небытие, кроме последнего, который выполняется первым вызовом mystery_func(), и единственный, который имеет целенаправленное возвращаемое значение.

В любом случае, улучшения, комментарии и упрощения наиболееприветствуется.

...