Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if valid template specialization

I want to check whether or not a template can be specialized using a given set of arguments. Here is the version for templates accepting only 1 argument:

#include <iostream>

template<template<typename...> class C, typename T>
struct is_valid_specialization {
    typedef struct { char _; } yes;
    typedef struct { yes _[2]; } no;

    template<template<typename...> class D, typename U>
    static yes test(D<U>*);
    template<template<typename...> class D, typename U>
    static no test(...);

    constexpr static bool value = (sizeof(test<C, T>(0)) == sizeof(yes));
};

template<typename T>
struct Test1 { };

template<typename T1, typename T2>
struct Test2 { };

template<typename...>
struct TestV { };

int main() {
    std::cout << "Test1<T>: " << is_valid_specialization<Test1, int>::value << std::endl;
    std::cout << "Test2<T>: " << is_valid_specialization<Test2, int>::value << std::endl;
    std::cout << "TestV<T>: " << is_valid_specialization<TestV, int>::value << std::endl;
}

This does the job for templates accepting only a single argument, but obviously I want to be able to use this with multiple arguments as well, so I tried this:

template<template<typename...> class C, typename... T>
struct is_valid_specialization {
    typedef struct { char _; } yes;
    typedef struct { yes _[2]; } no;

    template<template<typename...> class D, typename... U>
    static yes test(D<U...>*);
    template<template<typename...> class D, typename... U>
    static no test(...);

    constexpr static bool value = (sizeof(test<C, T...>(0)) == sizeof(yes));
};

Now this is where things get weird, because now value is always false.

Is there something I'm missing? What is so utterly different between these two versions? Is there another way to achieve this?

EDIT:
I've filed a bug report for both Clang and GCC

like image 933
Tom Knapen Avatar asked Jan 29 '14 16:01

Tom Knapen


1 Answers

The following is easier and works:

template<template<typename...> class C, typename... T>
struct is_valid_specialization {
    typedef struct { char _; } yes;
    typedef struct { yes _[2]; } no;

    template<template<typename...> class D>
    static yes test(D<T...>*);
    template<template<typename...> class D>
    static no test(...);

    constexpr static bool value = (sizeof(test<C>(0)) == sizeof(yes));
};

Live example

like image 172
Daniel Frey Avatar answered Oct 11 '22 15:10

Daniel Frey