4

Я пытаюсь написать некоторую функциональность, где мне нужно сохранить различные функции, а затем извлечь их типы аргументов. Поэтому я использую подпись функции как параметр шаблона. Но я получаю несколько неожиданные результаты. Вот код:Почему эти случаи C++ создают экземпляры разных шаблонов

#include <functional> 
#include <iostream> 

template <class T> 
struct foo 
{ 
    foo() 
    { 
     std::cout << "class T" << std::endl; 
    } 
}; 

template <class Ret, class Arg> 
struct foo<Ret(Arg)> 
{ 
    foo() 
    { 
     std::cout << "Ret(Arg)" << std::endl; 
    } 
}; 

template <class T> 
void save(std::function<T>) 
{ 
    new foo<T>(); 
} 

int main(int argc, char* argv[]) 
{ 
    std::function<void(void)> someFoo; 
    save(someFoo); 
    return 0; 
} 

Так что, если переменная someFoo функция с типом void(void), он конкретизирует первый шаблон, foo<T>. Но если я изменю его на void(int), я получаю желаемый специализированный шаблон, созданный. Почему это?

+0

'void (void)' такое же, как 'void()'. Второй параметр специализации нельзя сопоставить, чтобы он возвращался к основному шаблону. – 0x499602D2

+0

Можете проверить: http://stackoverflow.com/questions/693788/c-void-arguments –

ответ

5

В C++ наличие аргумента void на самом деле такое же, как отсутствие аргумента вообще (в отличие от C, кстати). Таким образом, он будет соответствовать специализации для Ret(), но он не может соответствовать специализации для Ret(Arg).

+0

В чем разница в 'c'? – maja

+0

@maja проверить мой комментарий выше в вопросе –

+0

В C аргумент 'void' - единственный способ сказать, что у вас нет аргументов. Если вы не помещаете ничего между скобкой, это означает, что у вас есть неопределенное количество аргументов. – Arkanosis

3

void(void) - это то же самое, что и void() - второй вариант void не является обязательным и не имеет значения.

Именно поэтому используется первый шаблон без параметров.