Удержание типа вложенного шаблона вариационного нетипичного списка

Рассмотрим следующие классы:

template<class T, int...> struct MyClass1 {};
template<class T, unsigned int...> struct MyClass2 {};
template<class T, long long int...> struct MyClass3 {};
template<class T, unsigned long long int...> struct MyClass4 {};

Я не могу изменить эти классы.

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

something<MyClass1>::type (-> int)
something<MyClass2>::type (-> unsigned int)
something<MyClass3>::type (-> long long int)
something<MyClass4>::type (-> unsigned long long int)

а также size_t если список переменных пуст?

3

Решение

Я не мог придумать способ определить один общий метафункция, которая делает это, но вот возможный обходной путь:

#include <iostream>
#include <type_traits>

using namespace std;

// PRIMARY TEMPLATE

template<typename T>
class something
{
};

// SPECIALIZATIONS FOR int

template<typename T, int... U, template<typename, int...> class L>
class something<L<T, U...>>
{
public:
typedef int type;
};

template<typename T, template<typename, int...> class L>
class something<L<T>>
{
public:
typedef size_t type;
};

// SPECIALIZATIONS FOR unsigned int

template<typename T, unsigned int... U, template<typename, unsigned int...> class L>
class something<L<T, U...>>
{
public:
typedef unsigned int type;
};

template<typename T, template<typename, unsigned int...> class L>
class something<L<T>>
{
public:
typedef size_t type;
};

/* ... OTHER SPECIALIZATIONS ... */

struct A {};
struct B {};

int main()
{
static_assert(is_same<something<MyClass1<A, 1, 2>>::type, int>::value, "Error!");
static_assert(is_same<something<MyClass1<A>>::type, size_t>::value, "Error!");
static_assert(is_same<something<MyClass2<B, 1U, 2U, 3U>>::type, unsigned int>::value, "Error!");
static_assert(is_same<something<MyClass2<B>>::type, size_t>::value, "Error!");
return 0;
}

Я пытался написать только одну специализацию, которая охватывала бы все случаи, например:

template<typename U, typename T, U... V, template<typename, U...> class L>
class something<L<T, V...>>
{
public:
typedef U type;
};

Но Clang 3.2 жалуется, что тип U не может быть выведен, поэтому эта специализация get_type никогда не будет использоваться. Поэтому, если вы будете следовать этому подходу, вам придется четко определить каждую специализацию. Это может или не может быть приемлемым в зависимости от ваших случаев использования. Надеюсь, поможет.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]