Как отмечено в других ответах, разрешение шаблона не может учитывать неявные преобразования.Простой способ решить проблему - перегрузить myFunc
и выполнить явное приведение.Рассмотрим следующий код:
#include <vector>
#include <iostream>
template <typename T>
class A{
public:
A() { };
~A() { };
// ...
template <typename outT = T> operator std::vector<outT>() const { /* implicit/explicit cast to std::vector */
std::cout << "I am doing a conversion" << std::endl;
return std::vector<outT>(); }
};
template <typename T = float, typename... Args>
void myFunc(const std::vector<T, Args...>& _arg){
std::cout << "myFunc" << std::endl;
}
template <typename T>
void myFunc(const A<T>& _arg)
{
std::cout << "I am the second variant of myFunc" << std::endl;
myFunc(static_cast<const std::vector<T>>(_arg));
}
int main(int argc, char const *argv[]) {
A<int> foo;
std::cout << "-- First call of myFunc" << std::endl;
myFunc(foo);
std::cout << "-- Second call of myFunc" << std::endl;
std::vector<double> x = foo;
myFunc(x);
return 0;
}
Вывод программы:
-- First call of myFunc
I am the second variant of myFunc
I am doing a conversion
myFunc
-- Second call of myFunc
I am doing a conversion
myFunc
Когда вы передаете foo
в myFunc
, компилятор использует вторую перегрузку myFunc
, котораячерез явное приведение вызывает оператор преобразования.Во втором случае мы непосредственно присваиваем foo
std::vector
, следовательно, выполняем преобразование перед передачей результирующего std::vector
первой перегрузке myFunc
.Обратите внимание:
вам необходим оператор преобразования const
, если вы хотите сохранить постоянство при перегрузках myFunc
.
васнужен дополнительный пакет параметров шаблона typename... Args
при первой перегрузке myFunc
для захвата каждой специализации std::vector
(скажем, с пользовательским распределителем).
Другой вариант может бытьобъявить A
как класс, производный от std::vector
.Что-то вроде следующего кода:
#include <vector>
#include <iostream>
template <typename T>
class A : public std::vector<T> {
public:
A() : std::vector<T>(/* Some parameters to initialize the base class */) { }
};
template <typename T = float, typename... Args>
void myFunc(const std::vector<T, Args...>& _arg){
std::cout << "myFunc" << std::endl;
}
int main(int argc, char const *argv[]) {
A<int> foo;
myFunc(foo);
return 0;
}
В этом случае вам не нужно преобразование, и вы вызываете myFunc
путем нарезки.Недостатком этого подхода является то, что вы выполняете преобразование в std::vector
в конструкторе, и каждый раз, когда вы изменяете A
, вы должны поддерживать данные базового класса std::vector
в актуальном состоянии.