Почему этот код не компилируется?
#include <iostream>
#include <vector>
template<class T>
class vector_ref
{
public:
vector_ref(T *pData, int pN) {Data = pData; N = pN;};
T *Data;
int N;
vector_ref<T>& operator=(const std::vector<T> &v1)
{
for(int ii = 0; ii < N; ii++)
{
Data[ii] = v1[ii];
}
return *this;
};
operator std::vector<T>()
{
std::vector<T> v1(N);
for(int ii = 0; ii < N; ii++)
{
v1[ii] = Data[ii];
}
return v1;
};
};
template<class T>
void printVec(std::vector<T> v1)
{
for(int ii = 0; ii < v1.size(); ii++)
{
std::cout << v1[ii] << std::endl;
}
}
int main()
{
std::vector<double> v;
v.push_back(1.0);
v.push_back(2.0);
v.push_back(3.0);
vector_ref<double> v_ref(&v[0],3);
printVec(v_ref); // Compiler error
return 0;
}
Я собираю с g++ 4.7.3
используя команду: g++ test.cpp
, Сообщение об ошибке:
test.cpp: In function ‘int main()’:
test.cpp:56:19: error: no matching function for call to ‘printVec(vector_ref<double>&)’
test.cpp:56:19: note: candidate is:
test.cpp:40:6: note: template<class T> void printVec(std::vector<T>)
test.cpp:40:6: note: template argument deduction/substitution failed:
test.cpp:56:19: note: ‘vector_ref<double>’ is not derived from ‘std::vector<T>’
это ответ предыдущий вопрос, кажется, предполагает, что это должно работать.
Как говорится в сообщении об ошибке:
test.cpp:56:19: error: no matching function for call to ‘printVec(vector_ref<double>&)’
Конечно же, эта строка:
vector_ref<double> v_ref(&v[0],3);
printVec(v_ref); // Compiler error
Обратите внимание, что v_ref
это vector_ref<double>
, Теперь сообщение об ошибке полезно указать, что есть printVec
функция, но она другая:
test.cpp:56:19: note: candidate is:
test.cpp:40:6: note: template<class T> void printVec(std::vector<T>)
И если мы перейдем к строке 40 и посмотрим на функцию printVec, вы увидите:
template<class T>
void printVec(std::vector<T> v1)
Итак, вот что это значит:
std::vector<T>
в качестве аргумента.vector_ref<double>
в качестве аргумента.Вот что означает сообщение об ошибке.
Теперь я вижу, что вы пытаетесь создать что-то, что может быть неявно преобразовано в вектор. Это становится грязным из-за шаблонов. Этот подход работает для упаковки не шаблонных типов, но имеет проблемы с шаблонами, и вот почему:
Когда компилятор пытается разобраться с printVec(v_ref)
надо найти декларацию для такого printVec
, Он ищет то, что занимает vector_ref<double>
, но ничего не находит. Он находит функцию шаблона, поэтому он пытается определить, можно ли создать экземпляр функции шаблона для этого типа. Подпись для printVec
это то, что нужно std::vector<T>
и это не соответствует vector_ref<double>
, поэтому он не совпадает, и он движется дальше. Это действительно так просто, как «не соответствует, сдавайся и двигаться дальше». Он не будет пытаться делать какие-либо преобразования для вашего типа.
Чтобы решить эту проблему, вы можете добавить явный .toVector()
как предполагает Себастьян. Или это может сработать, чтобы явно создать экземпляр шаблона:
template<class T>
void printVec(std::vector<T> v1)
{
for(int ii = 0; ii < v1.size(); ii++)
{
std::cout << v1[ii] << std::endl;
}
}
template<> void printVec(std::vector<double> v1); // explicit instantiation
Это явно указывает компилятору на создание экземпляра метода шаблона для std::vector<double>
и затем, когда он пытается найти соответствие printVec(vector_ref<double>)
, он увидит два варианта — шаблонный метод и экземплярный метод. Метод шаблона, как и раньше, потерпит неудачу, но он может понять, что может выполнить неявное преобразование для использования экземпляра метода. это может быть работать, но я не проверял это.
Я не уверен, что это сработает, и .toVector()
определенно чище. Но явная реализация шаблона — это хитрый трюк, а иногда и полезный, поэтому я решил упомянуть об этом.
Ваше неявное преобразование в вектор& небезопасно и будет делать ужасные вещи. Убери это. И включите предупреждения вашего компилятора, потому что компилятор уже должен был кричать на вас.
Проблема вашей ошибки компилятора в том, что при выводе аргументов не учитываются преобразования; он выполняет строгое сопоставление с образцом между типом аргумента и шаблоном типа параметра. И нет никакого совпадения между vector<T>
а также vector_ref<double>
,
Вы не можете заставить эту линию работать. Либо дать vector_ref
полный интерфейс вектора и сделать printVec
полный шаблон или использовать явное приведение или явную функцию преобразования, например, v_ref.to_vector()
,
Смотри Себастьян Редл & Тим отвечает за то, почему не удалось скомпилировать
Вы можете перегрузить ()
: похожий на to_vector
функция, как предложил Себастьян Редл
std::vector<T> operator() ()
{
std::vector<T> v1(N);
for(int ii = 0; ii < N; ii++)
{
v1[ii] = Data[ii];
}
return v1;
}
затем использует
printVec(v_ref());
Увидеть Вот