Мои первоначальные рассуждения о том, почему следующие фрагменты работают неправильно, но, поскольку @NathanOliver помог мне (см. Ниже), вот пересмотренное объяснение: Во время вывода аргументов шаблона преобразования типов не выполняются. Передача указателя на функцию, которая принимает аргумент std::function
, требует такого преобразования. Чтобы обойти эту проблему, вы можете вызвать метод, подобный этому
test2.add(std::function<void(int)>(func));
или измените определение Test2
на
class Test2
{
template<typename ...ARGS>
void add(void(*)(ARGS...)) {}
}
, который работает вместе с исходным вызовом
test2.add<int>(func);
В обоих примерах преобразование не требуется. Вызов Test1::add
сработал, потому что перед вызовом метода был выполнен вывод типа шаблона, следовательно, преобразование может иметь место.
Обратите внимание, что та же проблема возникает, когда Test2
объявлен с одним единственным параметром шаблона,
class Test2
{
template<typename T>
void add(const std::function<void(T)>&) {}
}
со следующими вариантами использования на стороне вызывающего абонента:
test2.add<int>(func); // Conversion ok, function template specified
test2.add(std::function<void(int)>(func)); // Type deduction, no conversion
test2.add(func); // Error, conversion AND type deduction