Частичная специализация шаблона - PullRequest
0 голосов
/ 08 марта 2011
template<class T>
struct TypeX;

template<>
struct TypeX<int(...)>//HERE IF WITHOUT ELLIPSIS IT WILL COMPILE
{
    static std::string get_type()
    {
        return "int()";
    }
};

template<>
struct TypeX<int>
{
    static std::string get_type()
    {
        return "int";
    }
};

template<class T>
struct type_descriptor
{
    typedef T type;
    typedef typename std::remove_reference<T>::type no_ref_type;
    typedef typename std::remove_pointer<no_ref_type>::type no_ref_no_pointer_type;
    typedef typename std::remove_cv<no_ref_no_pointer_type>::type no_ref_no_pointer_no_cv_type;
    typedef typename std::remove_all_extents<no_ref_no_pointer_no_cv_type>::type no_ref_no_pointer_no_cv_no_ext_type;
    typedef no_ref_no_pointer_no_cv_no_ext_type bare_type;

    enum {isArray = std::is_array<T>::value, isPointer = std::is_pointer<T>::value, isRef = std::is_reference<T>::value};

    static std::string get_type()
    {
        return pointer_<isPointer>() + array_<std::is_array<no_ref_no_pointer_type>::value>() + TypeX<bare_type>::get_type();

    }
};
template<bool C>
std::string array_()
{return "";}

template<>
std::string array_<true>()
{return "array of";}

template<bool C>
std::string pointer_()
{return "";}

template<>
std::string pointer_<true>()
{return "pointer to";}

int _tmain(int argc, _TCHAR* argv[])
{
    cout << type_descriptor<int(*)()>::get_type();

    return 0;
}

Пожалуйста, смотрите комментарий в коде. Вопрос в том, почему, если я специализируюсь на многоточии, которое подразумевает любое число, я получаю ошибку, но когда я специализируюсь на отсутствии аргументов, он компилируется?

Ответы [ 2 ]

1 голос
/ 08 марта 2011

Вопрос в том, почему, если я специализируюсь на многоточии, которое подразумевает любое число, я получаю ошибку, но когда я специализируюсь на отсутствии аргументов, она компилируется?

Потому что многоточие не подразумевает никаких скобок (так как вы пытаетесь использовать его в main). многоточие используется для обозначения переменного числа аргументов в функции (C ++ 03).


РЕДАКТИРОВАТЬ: Возможно, следующий пример дает вам достаточно подсказок для реализации того, что вы хотите:

template<class T>
struct TypeX
{
        TypeX() { cout << "TypeX" << endl; }
};

template<typename T>
struct TypeX<T(*)()> //will match with : int (*)(), char (*)(), etc!
{
        TypeX() { cout << "TypeX<T(*)()>" << endl; }
};

template<typename T, typename S>
struct TypeX<T(*)(S)> //will match with : int (*)(int), char (*)(int), etc!
{
        TypeX() { cout << "TypeX<T(*)(S)>" << endl; }
};

template<typename T, typename S, typename U>
struct TypeX<T(*)(S, U)> //will match with : int (*)(int, char), char (*)(int, int), etc!
{
       TypeX() { cout << "TypeX<T(*)(S, U)>" << endl; }
};
int main() {
        TypeX<int*>();
        TypeX<int(*)()>();
        TypeX<int(*)(int)>();
        TypeX<int(*)(char)>();
        TypeX<int(*)(char, int)>();
        TypeX<int(*)(short, char)>();
        return 0;
}

Вывод:

TypeX
TypeX<T(*)()>
TypeX<T(*)(S)>
TypeX<T(*)(S)>
TypeX<T(*)(S, U)>
TypeX<T(*)(S, U)>

Демонстрация на ideone: http://www.ideone.com/fKxKK

0 голосов
/ 10 марта 2011

Elipsis означает, что функция может принимать любое количество аргументов в каждом месте вызова.

int f(...);  // signature

int x = f();   // invocations
int y = f(my_int, my_double);

Сама сигнатура функции отличается от более конкретных сигнатур, наивно подразумеваемых каждымвызов (т. е. int f(), int f(int, double)).

Поэтому, в то время как вы можете специализироваться для случая int (*)(...), будет соответствовать только тип функции, который фактически определяет начальный elipsis.Другие функции, такие как int (*)(int), не совпадают.

...