Шаблонная проблема вызывает ошибку компоновщика (C++)

3-й параметрический усилитель copyOfRange является индексом copyTo, эксклюзивным из элемента - т.е. элемент в индексе copyTo не копируется. Таким образом, Вам нужен arr.length там & не arr.length - 1

https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#copyOfRange (булевская переменная [], %20int, %20int)

from - the initial index of the range to be copied, **inclusive**
to - the final index of the range to be copied, **exclusive**. 
     (This index may lie outside the array.)

, Таким образом, Вам нужно searchItem (Arrays.copyOfRange (arr, 1, arr.length), searchValue)

А, намного более простая рекурсивная программа - это

if(arr.length == 0)
    return false;

if(arr[0].compareTo(searchValue) == 0)
    return true;

return searchItem(Arrays.copyOfRange(arr, 1, arr.length), searchValue);    

44
задан chollida 30 October 2009 в 14:30
поделиться

5 ответов

You have to have your template definitions available at the calling site. That means no .cpp files.

The reason is templates cannot be compiled. Think of functions as cookies, and the compiler is an oven.

Templates are only a cookie cutter, because they don't know what type of cookie they are. It only tells the compiler how to make the function when given a type, but in itself, it can't be used because there is no concrete type being operated on. You can't cook a cookie cutter. Only when you have the tasty cookie dough ready (i.e., given the compiler the dough [type])) can you cut the cookie and cook it.

Likewise, only when you actually use the template with a certain type can the compiler generate the actual function, and compile it. It can't do this, however, if the template definition is missing. You have to move it into the header file, so the caller of the function can make the cookie.

74
ответ дан 26 November 2019 в 21:40
поделиться

Did you put your template function definition in a cpp file? Then move it to the header and inline it.

0
ответ дан 26 November 2019 в 21:40
поделиться

Вероятно, вы страдаете от отсутствия действительного экземпляра. Если вы поместите определение шаблона в отдельный файл .cpp, то при компиляции этого файла компилятор может не знать, какие экземпляры вам нужны. И наоборот, на сайтах вызовов, которые будут создавать экземпляры правильной версии функции шаблона, если определение тела функции недоступно, компилятор не будет иметь информации для создания экземпляров требуемых специализаций.

У вас есть два варианта. Поместите тело функции для шаблона функции в файл заголовка.

например, в файл заголовка:

template <typename T>
inline T* find_name(std::vector<T*> v, std::string name)
{
    // ...
}

или явно создайте экземпляр шаблона в .cpp, где вы определили шаблон.

например, в исходном файле (возможно, потребуется #include в файле, который определяет Item ):

template <typename T>
T* find_name(std::vector<T*> v, std::string name)
{
    // ...
}

template Item* find_name<Item>(std::vector<Item*> v, std::string name);
51
ответ дан 26 November 2019 в 21:40
поделиться

Ответы здесь отличные.

Я просто добавлю, что это часто является причиной, по которой в проекте помимо файлов .h и .cpp . Часто встречаются файлы .inl . Определения шаблонов войдут в файл .inl .

Эти . Файлы inl означают встроенные и обычно включаются файлом .h с таким же префиксом имени в конце файла после всех объявлений заголовков. Это фактически делает их частью файла заголовка, но отделяет объявления от любых определений.

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

11
ответ дан 26 November 2019 в 21:40
поделиться

Я только что заметил, что у вас есть второй вопрос, на который, похоже, нет ответа:

Есть ли способ сделать параметр шаблона таким, чтобы он был подклассом определенного класса, т.е. шаблон?

Можно. Например, см. is_base_of в Boost.TypeTraits .

Однако мне любопытно: зачем вам это нужно? Обычно требования шаблона к его параметрам зависят не от самого типа параметра, а от того, какие выражения, включающие этот тип, являются допустимыми. Например, представьте, что у вас есть:

template<class T>
void foo(const T& t)
{
    if (t.foo()){
       t.bar("blah");
    }
}

Утверждение, что T должен наследовать от чего-то вроде:

class HasFooAndBar
{
public:
  void foo()const;
  void bar(const char*)const;
};

, ничего не приносит, потому что создание экземпляра функции все равно завершится ошибкой, если тип не поддерживает операции. Более того, это без нужды ограничивает применимость foo () . Фактически, foo ' Любые требования заключаются в том, что t.foo () и t.bar (const char *) являются допустимыми выражениями для const T. Например, этот тип не наследуется от HasFooAndBar и все еще является допустимый параметр foo ():

struct DifferentFromHasFooAndBar
{
  bool foo()const;
  std::string bar(const std::string&)const;
};
1
ответ дан 26 November 2019 в 21:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: