Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.63/16: Рейтинг темы: голосов - 16, средняя оценка - 4.63
Dani
1395 / 639 / 134
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
Завершенные тесты: 1
1

Шаблоны. Ошибка компиляции: "Не удается сопоставить определение функции существующему объявлению"

01.09.2014, 00:31. Просмотров 2958. Ответов 11
Метки нет (Все метки)

vector.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#pragma once
#ifndef _VECTOR_H
#define _VECTOR_H
 
 
#include <exception>
 
 
template<typename T> class vector {
    public:
        vector(unsigned int = 0, const T& = T());
        template<typename InputIterator> vector(InputIterator, InputIterator);
        vector(const vector<T>&);
        vector& operator=(const vector<T>&);
        ~vector();
        void reserve(unsigned int n);
        void push_back(const T&);
        unsigned int capacity() const { return _capacity; }
        unsigned int size() const { return _size; }
        T& at(unsigned int n);
        void clear();
        T& back();
        void assign(unsigned int n, const T& = T());
        template<typename InputIterator> void assign(InputIterator, InputIterator);
        T& operator[](unsigned int n) { return _elem[n]; }
    private:
        T* _elem;
        unsigned int _size, _capacity;
};
 
 
#endif //_VECTOR_H
vector.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include "vector.h"
 
 
template <typename T> vector<T>::vector(unsigned int n, const T& val)
{
    assign(n, val);
}
 
 
template <typename T, typename InputIterator> vector<T>::vector(InputIterator _first, InputIterator _last)
{
    assign(_first, _last);
}
 
 
template <typename T> vector<T>::vector(const vector<T>& v)
{
    reserve(v._size);
    for(int i=0; i<_size; ++i)
        _elem[i] = v._elem[i];
}
 
 
template <typename T> vector<T>::~vector()
{
    delete[] elem;
}
 
 
template <typename T> vector<T>& vector<T>::operator=(const vector<T>& v)
{
    _size = v._size;
    reserve(_size);
    for(int i=0; i<_size; ++i)
        _elem[i] = v._elem[i];
}
 
 
template <typename T> void vector<T>::reserve(unsigned int n)
{
    if(_capacity >= n)
        return;
    _capacity = 5*n/4;
    T* newElem = new T[_capacity];
    for(int i=0; i<_size; ++i)
        newElem[i] = _elem[i];
    delete[] _elem;
    _elem = newElem;
}
 
 
template <typename T> void vector<T>::push_back(const T& x)
{
    reserve(++_size);
    _elem[_size] = x;
}
 
 
template <typename T> T& vector<T>::at(unsigned int n)
{
    if(n < _size)
        return _elem[n];
    throw std::runtime_error("Vector range violation");
}
 
 
template <typename T> void vector<T>::clear()
{
    delete[] _elem;
    _size = 0;
    _capacity = 0;
}
 
 
template <typename T> T& vector<T>::back()
{
    if(_size == 0)
        throw std::runtime_error("Vector range violation");
    return _elem[_size-1];
}
 
 
template <typename T> void vector<T>::assign(unsigned int n, const T& val)
{
    reserve(n);
    _size = n;
    for(int i=0; i<_size; ++i)
        _elem[i] = val;
}
 
 
template <typename T, typename InputIterator> void vector<T>::assign(InputIterator _first, InputIterator _false)
{
    delete[] _elem;
    _size = 0;
    _capacity = 0;
    while(_first < _last)
        push_back(*(_first++));
}
Ошибка компиляции:
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
с:\vector.cpp(13): error C2244: vector<T>::{ctor}: не удается сопоставить определение функции существующему объявлению
1>          определение
1>          'vector<T>::vector(InputIterator,InputIterator)'
1>          существующие объявления
1>          'vector<T>::vector(const vector<T> &)'
1>          'vector<T>::vector(InputIterator,InputIterator)'
1>          'vector<T>::vector(unsigned int,const T &)'
1>с:\vector.cpp(99): error C2244: vector<T>::assign: не удается сопоставить определение функции существующему объявлению
1>          определение
1>          'void vector<T>::assign(InputIterator,InputIterator)'
1>          существующие объявления
1>          'void vector<T>::assign(InputIterator,InputIterator)'
1>          'void vector<T>::assign(unsigned int,const T &)'
1>
1>Сбой построения.
В чем проблема?
0
QA
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.09.2014, 00:31
Ответы с готовыми решениями:

Ошибка при компиляции: "Не удается найти указанный файл"
Всех С Новым Годом!!! При компиляции в VS 12 у меня выдает ошибку. Пробовал в VS 10...

Ошибка при компиляции C++: "Не удается открыть файл включение: VersionHelpers.h"
Всем привет, есть код, при компиляции в VS 2010 возникает ошибка error C1083: Не удается открыть...

Ошибка компиляции. Не удается открыть файл включение: "no such file or directory". - C++
#include &lt;windows.h&gt; #include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;math.h&gt; #include...

Ошибка компиляции. Не удается открыть файл включение: "no such file or directory".
а именно на эту #include &quot;help.h&quot; #include &quot;stdafx.h&quot; #include &quot;help.h&quot; #include &lt;iostream&gt;...

Ошибка компиляции: "Не удается найти файл..."
Поставил VS2013, создал первое консольное приложение С++ (назвал 001), написал helloworld'овский...

11
Vourhey
Почетный модератор
6577 / 2341 / 199
Регистрация: 29.07.2006
Сообщений: 12,714
01.09.2014, 00:54 2
Лучший ответ Сообщение было отмечено Dani как решение

Решение

Цитата Сообщение от Dani Посмотреть сообщение
В чем проблема?
C++
1
2
3
4
5
6
template <typename T>
template <typename InputIterator>
vector<T>::vector(InputIterator _first, InputIterator _last)
{
    assign(_first, _last);
}
1
Dani
1395 / 639 / 134
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
Завершенные тесты: 1
01.09.2014, 01:05  [ТС] 3
Теперь пишет ошибку линковки, что не может найти конструктор и деструктор. Что еще не так?
Вот так главный файл выглядит (откуда вызываю эти функции):
C++
1
2
3
4
5
6
#include "vector.h"
 
int main()
{
    vector<int> arr(5);
}
Bash
1
2
3
1>1.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall vector<int>::vector<int>(unsigned int,int const &)" (??0?$vector@H@@QAE@IABH@Z) в функции _main
1>1.obj : error LNK2019: ссылка на неразрешенный внешний символ "public: __thiscall vector<int>::~vector<int>(void)" (??1?$vector@H@@QAE@XZ) в функции _main
1>C:\1.exe : fatal error LNK1120: неразрешенных внешних элементов: 2
0
Vourhey
Почетный модератор
6577 / 2341 / 199
Регистрация: 29.07.2006
Сообщений: 12,714
01.09.2014, 01:11 4
Лучший ответ Сообщение было отмечено Dani как решение

Решение

Цитата Сообщение от Dani Посмотреть сообщение
Что еще не так?
Имплементацию шаблонов размести в .h файле, а не в отдельном .cpp.
2
01.09.2014, 01:11
Dani
1395 / 639 / 134
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
Завершенные тесты: 1
01.09.2014, 01:17  [ТС] 5
А это всегда так положено имплементацию шаблонов писать в .h файле? Или это причуды студии?
0
Vourhey
Почетный модератор
6577 / 2341 / 199
Регистрация: 29.07.2006
Сообщений: 12,714
01.09.2014, 01:27 6
Цитата Сообщение от Dani Посмотреть сообщение
А это всегда так положено имплементацию шаблонов писать в .h файле? Или это причуды студии?
Не обязательно в .h. Импелементация должна быть в одной единице трансляции с кодом, который ее использует. Так как шаблон должен быть инстанцирован уже на стадии компиляции, то компилятор должен иметь доступ к реализации. В случае с подключением .h где только объявление, компилятор не знает, откуда ему брать имплементацию.
Почитай здесь: http://www.bogotobogo.com/cplusplus/...ation_file.php

Добавлено через 3 минуты
Ну и цитату из книги Страуструпа заодно:
For technical and historical reasons, option #3, the separate compilation of template definitions an their uses, is not offered. By far the most common approach is to include the definition of the templates you use in every translation unit in which you use them...
1
Dani
1395 / 639 / 134
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
Завершенные тесты: 1
01.09.2014, 01:39  [ТС] 7
Спасибо большое за ссылку.
Вот немного подправил код:
vector.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#pragma once
#ifndef _VECTOR_H
#define _VECTOR_H
 
 
#include <exception>
 
 
template<typename T> class vector {
    public:
        vector(unsigned int = 0, const T& = T());
        template<typename InputIterator> vector(InputIterator, InputIterator);
        vector(const vector<T>&);
        vector& operator=(const vector<T>&);
        ~vector();
        void reserve(unsigned int n);
        void push_back(const T&);
        unsigned int capacity() const { return _capacity; }
        unsigned int size() const { return _size; }
        T& at(unsigned int n);
        void clear();
        T& back();
        void assign(unsigned int n, const T& = T());
        template<typename InputIterator> void assign(InputIterator, InputIterator);
        T& operator[](unsigned int n) { return _elem[n]; }
    private:
        T* _elem;
        unsigned int _size, _capacity;
};
 
 
template<typename T> vector<T>::vector(unsigned int n, const T& val) : _size(0), _capacity(0)
{
    assign(n, val);
}
 
 
template<typename T> template<typename InputIterator> vector<T>::vector(InputIterator _first, InputIterator _last) : _size(0), _capacity(0)
{
    assign(_first, _last);
}
 
 
template<typename T> vector<T>::vector(const vector<T>& v) : _size(0), _capacity(0)
{
    reserve(v._size);
    for(unsigned int i=0; i<_size; ++i)
        _elem[i] = v._elem[i];
}
 
 
template<typename T> vector<T>::~vector()
{
    if(_capacity > 0)
        delete[] _elem;
}
 
 
template<typename T> vector<T>& vector<T>::operator=(const vector<T>& v)
{
    _size = v._size;
    reserve(_size);
    for(unsigned int i=0; i<_size; ++i)
        _elem[i] = v._elem[i];
}
 
 
template<typename T> void vector<T>::reserve(unsigned int n)
{
    if(_capacity >= n)
        return;
    unsigned int newCapacity = 5*n/4;
    T* newElem = new T[newCapacity];
    for(unsigned int i=0; i<_size; ++i)
        newElem[i] = _elem[i];
    if(_capacity > 0)
        delete[] _elem;
    _elem = newElem;
    _capacity = newCapacity;
}
 
 
template<typename T> void vector<T>::push_back(const T& x)
{
    reserve(++_size);
    _elem[_size] = x;
}
 
 
template<typename T> T& vector<T>::at(unsigned int n)
{
    if(n < _size)
        return _elem[n];
    throw std::runtime_error("Vector range violation");
}
 
 
template<typename T> void vector<T>::clear()
{
    if(_capacity > 0)
        delete[] _elem;
    _size = 0;
    _capacity = 0;
}
 
 
template<typename T> T& vector<T>::back()
{
    if(_size == 0)
        throw std::runtime_error("Vector range violation");
    return _elem[_size-1];
}
 
 
template<typename T> void vector<T>::assign(unsigned int n, const T& val)
{
    reserve(n);
    _size = n;
    for(unsigned int i=0; i<_size; ++i)
        _elem[i] = val;
}
 
 
template<typename T> template<typename InputIterator> void vector<T>::assign(InputIterator _first, InputIterator _last)
{
    if(_capacity > 0)
        delete[] _elem;
    _size = 0;
    _capacity = 0;
    while((*_first) < (*_last))
        push_back(*(_first++));
}
 
 
#endif //_VECTOR_H
vector.cpp ---> удалил из-за ненадобности
main.cpp
C++
1
2
3
4
5
6
7
8
9
#include <iostream>
#include "vector.h"
 
int main()
{
    vector<double> arr(6, 5);
    for(int i=0; i<6; ++i)
        std::cout << arr[i] << ' ';
}
Ошибки:
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
c:\vector.h(130): error C2100: недопустимое косвенное обращение
1>          c:\vector.h(40): см. ссылку на создание экземпляров функции шаблон при компиляции "void vector<T>::assign<InputIterator>(InputIterator,InputIterator)"
1>          with
1>          [
1>              T=double,
1>              InputIterator=int
1>          ]
1>          c:\vector.h(40): см. ссылку на создание экземпляров функции шаблон при компиляции "void vector<T>::assign<InputIterator>(InputIterator,InputIterator)"
1>          with
1>          [
1>              T=double,
1>              InputIterator=int
1>          ]
1>          c:\main.cpp(6): см. ссылку на создание экземпляров функции шаблон при компиляции "vector<T>::vector<int>(InputIterator,InputIterator)"
1>          with
1>          [
1>              T=double,
1>              InputIterator=int
1>          ]
1>          c:\main.cpp(6): см. ссылку на создание экземпляров функции шаблон при компиляции "vector<T>::vector<int>(InputIterator,InputIterator)"
1>          with
1>          [
1>              T=double,
1>              InputIterator=int
1>          ]
1>с:\vector.h(131): error C2100: недопустимое косвенное обращение
Как я понимаю это из-за того, что оно вызывает конструктор для итераторов. Но почему он его вызывает? И как это исправить?
0
DrOffset
10802 / 5755 / 1414
Регистрация: 30.01.2014
Сообщений: 9,242
01.09.2014, 01:53 8
Цитата Сообщение от Dani Посмотреть сообщение
Но почему он его вызывает? И как это исправить?
Лучше подходит потому что. Передавать правильный тип
C++
1
vector<double> arr(6, 5.0);
1
gray_fox
What a waste!
1561 / 1265 / 168
Регистрация: 21.04.2012
Сообщений: 2,649
Завершенные тесты: 3
01.09.2014, 01:53 9
Цитата Сообщение от Dani Посмотреть сообщение
Как я понимаю это из-за того, что оно вызывает конструктор для итераторов. Но почему он его вызывает?
Потому что best match. Типы аргументов - (int, int), а не (unsigned int, double), как в другом конструкторе.
Цитата Сообщение от Dani Посмотреть сообщение
И как это исправить?
Можно исключить этот конструктор из набора рассматриваемых перегрузок, если инстанциированный тип - не итератор, с помощью SFINAE. Вроде в std::vector именно так и сделано.
1
Dani
1395 / 639 / 134
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
Завершенные тесты: 1
01.09.2014, 01:54  [ТС] 10
DrOffset, и при vector<int> arr(6, 5) тоже лучше итераторный конструктор подходит
0
ASCII
97 / 70 / 13
Регистрация: 15.12.2013
Сообщений: 453
Завершенные тесты: 2
01.09.2014, 02:31 11
Dani, в срр файле передопределением функции вроде надо написать export и можно будет по идее раздельно компилировать определения и объявления... Попробуй

Добавлено через 9 минут
Ошибся, в h файле перед объявлением
1
DrOffset
10802 / 5755 / 1414
Регистрация: 30.01.2014
Сообщений: 9,242
01.09.2014, 18:16 12
Цитата Сообщение от Dani Посмотреть сообщение
и при vector<int> arr(6, 5) тоже лучше итераторный конструктор подходит
Да, потому что первый аргумент unsigned int, а 6 имеет тип int. Стандартный вектор, между прочим, себя так же ведет.
Лечится, опять же, передачей правильных типов:
C++
1
vector<int> arr(6u, 5);
Или через enable_if, как советовали выше.
1
01.09.2014, 18:16
Answers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.09.2014, 18:16

Шаблоны, ошибка "неоднозначный вызов перегруженной функции"
#include &lt;iostream&gt; using namespace std; void CheckInput(int &amp;); void CheckInput(double &amp;);...

Шаблоны класса:Матрица. Ошибка бинарный "=": не найден оператор, принимающий правый операнд типа "Matr<T>"
Выдает ошибку &quot;бинарный &quot;=&quot;: не найден оператор, принимающий правый операнд типа &quot;Matr&lt;T&gt;&quot; (или...

Ошибка "при попытке сопоставить список аргументов"
программа : #include &lt;iostream&gt; #include &lt;conio.h&gt; using std::endl; using std::cin;...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
12
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru