Параметр шаблона шаблона со смешанным типом и нетипичными переменными параметрами - PullRequest
0 голосов
/ 16 мая 2019

У меня возникают проблемы при объявлении следующего:

// c++17
template<typename T, typename ...Before, T v, typename ...After, template<typename ..., T, typename ...> U>
auto enum_to_type() {
    // do things with
    // U<Before..., v, After...> obj;
    // as an example:
    return U<Before..., v + 1, After...>{};
}

// demonstrate of usage

template<int v>
struct A {};

template<typename T, int v>
struct B {};

/// call enum_to_type to get next type
/// note: the following does not compile
using next_A = decltype(enum_to_type<int, 0, A>()); 
// == A<1>
template<typename T>
using next_B = decltype(enum_to_type<int, T, 0, B>()); 
// == B<1>


Цель этой функции - написать общий код, который может использовать параметр шаблона нетипичного типа v для создания класса шаблона из шаблона классаU без знания того, как параметры шаблона объявлены в U.В противном случае нужно написать эту функцию для разных подписей, например, U<T v>, U<typename, T v>, U<T v, typename> и т. Д.

Редактировать: я думаю, что то, что я хочу, скорее всего, невозможно.

1 Ответ

2 голосов
/ 16 мая 2019

Возможно с некоторыми модификациями:

//type container template
template<typename...>
struct types{};
//declaration
template<typename ,auto V, typename, template<typename ,decltype(V), typename...>class>
class enum_to_type;
//generic definition
template<typename First, typename ... Befors, First V, typename ... Afters, template<typename ,First, typename...>class U>
class enum_to_type<types<First, Befors...>, V, types<Afters...>, U>{
public:
    static auto go(){
        return U<types<Befors...>, V + 1, Afters...>{};
    }
};
//specialization
template<auto V, typename ... Afters, template<typename ,decltype(V), typename...>class U>
class enum_to_type<types<>, V,types<Afters...>, U>{
public:
    static auto go(){
        return U<types<>, V + 1, Afters...>{};
        //or
        //return U<types<>, V, Afters...>{};
    }
};
//Declarations and specializations for the target class templates
template<typename, int>
struct A{};

template<typename, int, typename>
struct B;
template<typename T, int V>
struct B<types<>, V, T > {};

using next_A = decltype(enum_to_type<types<int>,  0, types<>, A>::go());

template<typename T>
using next_B = decltype(enum_to_type<types<int>, 0, types<T>, B>());

template<typename, auto, typename...>
struct general_case;
template<typename ... befors, int V, typename ... afters>
struct general_case<types<befors...>, V, afters ...> {};

Использование:

decltype(enum_to_type<types<>,  0, types<>, A>::go()) object_A;
decltype(enum_to_type<types<>, 0, types<int>, B>::go()) object_B;
decltype(enum_to_type<types<int, float>, 3, types<int>, general_case>::go()) object_general;

Просто у компилятора нет способа узнать, сколько типов находится до и после. Вот почему в общем случае в объявлении шаблона может быть только один пакет аргументов. Но он может обрабатывать несколько пакетов аргументов в специализации!

Удачи!

...