문제

Consider the following classes:

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 {};

I cannot modify these classes.

Is it possible to write an helper class or function or something, that will return the type of the variadic list:

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

and size_t if the variadic list is empty ?

도움이 되었습니까?

해결책

I couldn't come up with a way to define one generic metafunction that does it, but here is a possible workaround:

#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;
}

I tried to write only single specialization that would cover all cases, like this:

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

But Clang 3.2 complains that the type of U cannot be deduced, so this specialization of get_type will never be used. So if you follow this approach you will have to explicitly define each specialization. This may or may not be acceptable depending on your use cases. Hope it helps.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top