Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
298 / 107 / 31
Регистрация: 12.03.2012
Сообщений: 449

Шаблоны: найти причины появления ошибок в коде

06.04.2018, 00:20. Показов 1125. Ответов 19
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Не смог придумать как конкретнее назвать тему
Ситуация следующая - есть классы:
C++
1
2
3
template<typename T>
class Foo;
class Bar;
Для класса Foo реализованы перегрузки
C++
1
2
template <typename T>
bool operator== (const Foo<T>& a, const Foo<T>& b)
и т.д.
создаются экземляры
C++
1
Foo<Bar> foobar1, foobar2;
но при попытке, например, сравнить (==) msvc выбрасывает
unresolved external symbol "bool __cdecl operator<(class Foo<class Bar> const &,class Foo<class Bar> const &)"
Почему так происходит я приблизительно догадываюсь, но вопрос в том, что с этим делать
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
06.04.2018, 00:20
Ответы с готовыми решениями:

Friend и Шаблоны: найти причины возникновения ошибок в коде и исправить эти ошибки
Есть такой минимальный код: #include &lt;string&gt; template&lt;typename CharT&gt; class Format { public: typedef...

Найти причины и способы исправления ошибок в коде
#include&lt;iostream&gt; #include&lt;iomanip&gt; #include&lt;stdio.h&gt; #include&lt;conio.h&gt; #include&lt;stdlib.h&gt; #include&lt;string.h&gt; using...

Найти причины и способы исправления ошибок в коде
ввожу: 2 + тут он мне пишет &quot;???&quot; #include &lt;stdio.h&gt; #include &lt;iostream&gt; #include &lt;string&gt; int main(void) { int...

19
6 / 6 / 7
Регистрация: 04.04.2018
Сообщений: 22
06.04.2018, 00:38
Вы бы полный код скинули. Или, как часто просят на stackOverflow - минимальный код, воспроизводящий проблему. Обычно такая ошибка означает, что ваша функция объявлена, но не определена.
0
298 / 107 / 31
Регистрация: 12.03.2012
Сообщений: 449
06.04.2018, 01:09  [ТС]
Сейчас до него, к сожалению, добраться не могу, но функция точно определена именно так, как я описал выше
Внутри определённым образом сравниваются элементы (в реальности Foo - связный список, Bar - строка)

Добавлено через 8 минут
Суть в том, что если перегрузку объявить как
C++
1
inline bool operator< (const Foo<Bar>& a, const Foo<Bar>& b)
то все прекрасно соберется
т.е. дело именно в том что шаблон не генерится, но что делать - для меня остается загадкой

Добавлено через 7 минут
Обнаружил, что если перенести функцию в класс (friend), все компилится нормально... Можно как-то обойти этот момент и реализацию функции оставить вне класса?
0
Велосипедист...
 Аватар для Mournful Max
353 / 220 / 73
Регистрация: 15.12.2015
Сообщений: 785
06.04.2018, 01:17
h3mbr0, нужен код. Вторым сообщением только запутали.
0
354 / 135 / 28
Регистрация: 16.12.2012
Сообщений: 607
Записей в блоге: 1
06.04.2018, 01:24
Написал за ради теста.. Вроде как работает..
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
#include <iostream>
 
using namespace std;
 
template <typename T>
class lst {
public:
    lst() { head = nullptr; }
    void push_front(T data) {
        head = new node(data, head);
    }
 
    bool operator==(const lst<T>& b) {
        node *ah = this->head, *bh = b.head;
        while(ah != nullptr && bh != nullptr) {
            if (!(ah->data == bh->data)) return false;
            ah = ah->next;
            bh = bh->next;
        }
        return (ah == nullptr && bh == nullptr);
    }
private:
    struct node {
        T data;
        node *next;
 
        node(T data, node* next = nullptr):data(data), next(next) {} 
    };
 
    node *head;
};
 
template <typename T>
class smdata {
public:
    smdata(T data):data(data) {}
    bool operator==(const smdata<T>& b) {
        return this->data == b.data;
    }
private:
    T data;
};
 
int main() {
    lst<smdata<string> > a, b;
    a.push_front(smdata<string>("1"));
    b.push_front(smdata<string>("14"));
    cout << (a == b) << endl;
    return 0;
}
1
6 / 6 / 7
Регистрация: 04.04.2018
Сообщений: 22
06.04.2018, 01:26
Вообще, как минимум, я тут вижу проблему в том, что у вас объявлен operator=, а компилятор хочет operator<.
0
298 / 107 / 31
Регистрация: 12.03.2012
Сообщений: 449
06.04.2018, 01:47  [ТС]
Ромаха, в ряде случаев это не работает - требует non-member перегрузку
Вот код(рабочий):
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
    friend bool operator== (const List& list1, const List& list2)
    {
        auto node1 = list1.get_head(),
            node2 = list2.get_head();
 
        while (node1 != nullptr && node2 != nullptr)
        {
            if (node1->get_info() != node2->get_info())
                return false;
 
            node1 = node1->get_next();
            node2 = node2->get_next();
        }
 
        return node1 == nullptr && node2 == nullptr;
    }
    friend bool operator< (const List& list1, const List& list2)
    {
        auto node1 = list1.get_head(),
            node2 = list2.get_head();
 
        while (node1 != nullptr && node2 != nullptr)
        {
            if (node1->get_info() < node2->get_info())
                return true;
            if (node1->get_info() > node2->get_info())
                return false;
 
            node1 = node1->get_next();
            node2 = node2->get_next();
        }
 
        return node1 == nullptr && node2 != nullptr;
    }
    friend bool operator> (const List& list1, const List& list2)
    {
        auto node1 = list1.get_head(),
            node2 = list2.get_head();
 
        while (node1 != nullptr && node2 != nullptr)
        {
            if (node1->get_info() > node2->get_info())
                return true;
            if (node1->get_info() < node2->get_info())
                return false;
 
            node1 = node1->get_next();
            node2 = node2->get_next();
        }
 
        return node1 != nullptr && node2 == nullptr;
    }
хотелось бы вынести его из описания класса
0
Велосипедист...
 Аватар для Mournful Max
353 / 220 / 73
Регистрация: 15.12.2015
Сообщений: 785
06.04.2018, 02:03
Цитата Сообщение от h3mbr0 Посмотреть сообщение
хотелось бы вынести его из описания класса
А где само определение класса ? Ничего не видно же... Непонятно, в class body этот код или нет... Или это вообще шаблон класса...
0
298 / 107 / 31
Регистрация: 12.03.2012
Сообщений: 449
06.04.2018, 03:04  [ТС]
friend не может быть не в class body, и да, это шаблон
Определение выше
Весь класс слишком большой
Я ведь и написал, что хочу описать эти friend функции вне класса, как это делается с другими методами
0
Велосипедист...
 Аватар для Mournful Max
353 / 220 / 73
Регистрация: 15.12.2015
Сообщений: 785
06.04.2018, 04:44
Ну вот как-то так пробуй:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template < class T >
bool operator ==( const T& list1, const T& list2 );
 
template < typename T >
class List
{
public:
    friend bool operator ==<>( const List< T >& list1, const List< T >& list2 );
};
 
template < class T >
bool operator ==( const T& list1, const T& list2 )
{
    ...
}
Добавлено через 5 минут
С operator < поступаешь так же:
– объявляешь шаблон функции сверху реализации шаблона класса ( как у меня, 1-2 строки );
фрэндишь специализацию ( 8 строка );
– пишешь реализацию ( 11-15 строки ).
1
354 / 135 / 28
Регистрация: 16.12.2012
Сообщений: 607
Записей в блоге: 1
06.04.2018, 10:47
Цитата Сообщение от h3mbr0 Посмотреть сообщение
Ромаха, в ряде случаев это не работает - требует non-member перегрузку
Г-да, кто пояснит?
0
 Аватар для Avaddon74
571 / 353 / 133
Регистрация: 15.09.2017
Сообщений: 1,239
06.04.2018, 11:19
h3mbr0, Насколько я понял вашу проблему. Вы вынесли перегрузку оператора вне класса, в друзья его не хотите добавлять, но сравнение происходит на основе закрытых переменных, внешняя перегрузка не может получить доступ к закрытым свойствам класса. Либо делайте их доступными извне, либо добавляете перегрузку в друзья, либо переносите перегрузку в класс.

Добавлено через 18 минут
Здесь я смог получить именно такую ошибку:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template<class T>
class Test {
    T a;
public:
    friend bool operator== (const Test<T> &obj1, const Test<T> &obj2);
};
 
template<class T>
bool operator== (const Test<T> &obj1, const Test<T> &obj2) {
    return obj1.a == obj2.a;
}
 
int main(){
    Test<int> obj1, obj2;
    obj1 == obj2;
}
0
298 / 107 / 31
Регистрация: 12.03.2012
Сообщений: 449
06.04.2018, 17:42  [ТС]
Captain Maxee,
<>
может в этом дело? позже попробую, спасибо



Цитата Сообщение от Ромаха Посмотреть сообщение
Г-да, кто пояснит?
binary '<': no operator found which takes a left-hand operand of type 'const List<String>' (or there is no acceptable conversion)


Цитата Сообщение от Avaddon74 Посмотреть сообщение
либо добавляете перегрузку в друзья
Цитата Сообщение от Avaddon74 Посмотреть сообщение
Здесь я смог получить именно такую ошибку:
friend bool operator== (const Test<T> &obj1, const Test<T> &obj2);
Вот именно этот момент меня и интересует. разве она не в друзьях? я понимаю, что дело, вероятно, в шаблонах, но в чем тут подвох?
0
Велосипедист...
 Аватар для Mournful Max
353 / 220 / 73
Регистрация: 15.12.2015
Сообщений: 785
06.04.2018, 18:40
Цитата Сообщение от Avaddon74 Посмотреть сообщение
C++
5
friend bool operator== (const Test<T> &obj1, const Test<T> &obj2);
Это не шаблонная функция, — шаблонные только ее параметры.
Реализация такой функции должна выглядеть, например, так:
C++
1
2
3
4
bool operator ==( const Test< int >& obj1, const Test< int >& obj2 )
{
    return obj1.a == obj2.a;
}
Цитата Сообщение от Avaddon74 Посмотреть сообщение
C++
8
9
10
11
template<class T>
bool operator== (const Test<T> &obj1, const Test<T> &obj2) {
    return obj1.a == obj2.a;
}
А это — да, шаблонная функция, но она никак не связана с этим объявлением:
Цитата Сообщение от Avaddon74 Посмотреть сообщение
C++
5
friend bool operator== (const Test<T> &obj1, const Test<T> &obj2);
Это можно проверить, сделав явный инстанс:
C++
1
template bool operator ==( const Test< int >& obj1, const Test< int >& obj2 );
Компилятор будет ругаться, что a находится в приватном секторе, а это значит, что friend никак не повлиял на эту функцию.
1
298 / 107 / 31
Регистрация: 12.03.2012
Сообщений: 449
06.04.2018, 18:51  [ТС]
Captain Maxee, разобрался, спасибо
код выше
C++
1
friend bool operator ==<>( const List< T >& list1, const List< T >& list2 );
сработал, но в чем тут секрет? что за <> и почему требуется объявить шаблон заранее?
0
Велосипедист...
 Аватар для Mournful Max
353 / 220 / 73
Регистрация: 15.12.2015
Сообщений: 785
06.04.2018, 19:14
Цитата Сообщение от h3mbr0 Посмотреть сообщение
что за <> и почему требуется объявить шаблон заранее?
Это специальный синтаксис для создания специализаций шаблонных функций в шаблонном классе.
Он состоит из 3 этапов, которые я описал в посте #10:
1. Объявление шаблона функции сверху реализации шаблона класса.
2. Создание конкретной специализации.
3. Реализация шаблона функции.
Вот тот же пример, взятый из #10 поста, с добавленными комментариями, где показаны все 3 этапа:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// > ---- ---- 1 ---- ----
template < class T >
bool operator ==( const T& list1, const T& list2 );
//   ---- ---- 1 ---- ---- <
 
template < typename T >
class List
{
public:
// > ---- ---- 2 ---- ----
    friend bool operator ==<>( const List< T >& list1, const List< T >& list2 );
//   ---- ---- 2 ---- ---- <
};
 
// > ---- ---- 3 ---- ----
template < class T >
bool operator ==( const T& list1, const T& list2 )
{
    ...
}
//   ---- ---- 3 ---- ---- <
Есть еще один путь ( он полегче, но менее деликатен ):
C++
1
2
3
4
5
6
7
8
9
10
11
12
template < typename TT >
class List
{
public:
    template < class T > friend bool operator ==( const T& list1, const T& list2 );
};
 
template < class T >
bool operator ==( const T& list1, const T& list2 )
{
    ...
}
Мне не то чтобы лень объяснять... я боюсь сказать лишнего, лишний раз ввести в заблуждение. Поэтому мне сложно привести различия между двумя видами записи. Но они есть. Возможно, кто-то из старших зайдет и расскажет об отличиях. Мне тоже было бы интересно послушать. Пока советую использовать первый синтаксис ( с предварительным объявлением ), так как он более практичен.
1
What a waste!
 Аватар для gray_fox
1610 / 1302 / 180
Регистрация: 21.04.2012
Сообщений: 2,733
06.04.2018, 19:15
Цитата Сообщение от h3mbr0 Посмотреть сообщение
что за <>
Это явная специализация шаблона функции (другом объявляется только она, а не шаблон).

Цитата Сообщение от h3mbr0 Посмотреть сообщение
почему требуется объявить шаблон заранее?
Нельзя объявлять/определять специализации без предварительного объявления самого шаблона.
2
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
07.04.2018, 00:14
Цитата Сообщение от h3mbr0 Посмотреть сообщение
Для класса Foo реализованы перегрузки
h3mbr0, я подозреваю, что грабли очень древние. Дело в том, что по принятой терминологии Foo это класс. Шаблонный класс. Но по сути это совсем не класс. Это шаблон для построения классов. То есть, Foo это не есть класс в том смысле, что class Bar, это класс. Однако, в мире программирования только бубен имеет более-менее точное определение. Хотя и его никто не знает.
В чём беда отождествления шаблона (схемы построения/определения типа) и класса (схемы уже известного типа)? В том, что начинает казаться что:
C++
1
2
3
4
template <class T>
bool operator == (const T& lhs, const T& rhs){
return lhs == rhs ;
}
это очём-то. А это не о чём. В том смысле, что если для T не определён оператор сравнения на равенство для константных ссылок, то работать оно не будет и сообщение будет похоже на то, что Вы получаете. Потому что класс получается при инстанцировании шаблона при конкретизации типа-параметра T, типом - Bar в Вашем случае. Если для Bar нет определения оператора, то не выведет компилятор ничего хорошего.
Это если я угадал о чём речь.
1
 Аватар для Avaddon74
571 / 353 / 133
Регистрация: 15.09.2017
Сообщений: 1,239
07.04.2018, 00:50
Captain Maxee, Я пытался получить ту же ошибку, что и у ТС, но к сожалению, мне пришлось срочно уехать, и я свои наблюдения не закончил, а позже я вообще не смог получить доступ к форуму (только сейчас у меня открылась страница). Я понимаю, что допускал ошибки в коде, но ещё раз повторюсь, это было умышленно, чтоб получить ту же ошибку, т.к. ТС код свой не предоставил. Моё сообщение и мой код, это всего-лишь размышления Я полностью согласен с вашими замечаниями, но закончить свою мысль я так и не успел. Но если честно, я до сих пор не могу понять, в чем именно была ошибка у ТС, т.к. код он свой не предоставляет.
2
298 / 107 / 31
Регистрация: 12.03.2012
Сообщений: 449
07.04.2018, 15:45  [ТС]
Avaddon74, ваш код выше максимально компактно воспроизвел именно мой случай
Собственно, проблема была именно в том, в чем я и предположил, и чуть выше приведены примеры ее решения
Вся сложность тут, как это обычно бывает с плюсами, была исключительно в нюансах
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
07.04.2018, 15:45
Помогаю со студенческими работами здесь

Найти причины и способы устранения ошибок в коде
Доброго времени суток! При компиляции появляются следующие ошибки! Помогите исправить их! 1) .cpp(911) : error C2039:...

Найти причины и способы исправления ошибок в коде
Здравствуйте!!! Недавно начал изучать С++. При запуске программы она ни чего не выдает т.е. начиная с бесконечного цикла for(;;) программа...

Найти причины и способы исправления ошибок в коде
Ансамбль песни и пляски «Четверочка» проводит очередной кастинг, в котором традиционно участвуют представители четырех городов. В итоговый...

Найти причины и способы устранения ошибок в коде
Прошу Вашей помощи. Я только начинаю изучать С++. Пытаюсь создать программу а он выдает ошибки 1&gt;------ Сборка начата: проект:...

Найти причины и способы исправления ошибок в коде
Почему она не компилируется? #include &lt;iostream.h&gt; #include &lt;algorithm&gt; using namespace std; int main() { int a; ...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru