Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
DiffEreD
1442 / 779 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
1

Ошибка: multiple definition of `void std::swap<A>(A&amp;, A&amp;)

04.08.2015, 19:46. Просмотров 1293. Ответов 46
Метки нет (Все метки)

Хочу специализировать swap для своего класса. Получаю ошибку. Вот код:
a.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef A_H
#define A_H
 
#include <string>
 
class A
{
    std::string str;
public:
    A() = default;
    A(const std::string &);
 
    void swap(A &) noexcept;
};
 
#endif // A_H
a.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include "a.h"
#include <utility>
 
A::A(const std::string &s) : str(s)
{}
 
void A::swap(A &other) noexcept
{
    using std::swap;
    swap(str, other.str);
}
 
namespace std
{
 
template <>
void swap(A &lhs, A &rhs) noexcept(noexcept(lhs.swap(rhs)))
{
    lhs.swap(rhs);
}
 
}
main.cpp
C++
1
2
3
4
5
6
7
8
9
#include <iostream>
#include <utility>
#include "a.h"
 
int main()
{
    A a1("Hello"), a2("world");
    std::swap(a1, a2);
}
Ошибка для специализации: multiple definition of `void std::swap<A>(A&, A&) В чем проблема?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
04.08.2015, 19:46
Ответы с готовыми решениями:

Выделение памяти для буффера, под std::istream& operator>>(std::istream &, String &)
Добрый день. Как осуществляется выделения памяти под перегруженный оператор...

в чем разница между void f(int &n) и void f(int &&n)
:help:

Почему friend ostrem& operator <<(ostream& outs, const Rational&); - invalid function declaration?
Пытаюсь скомпилировать программу пишет friend ostrem&amp; operator &lt;&lt;(ostream&amp;...

В заштрихованную фигуру бросают точки с координатами x и y. Получить координаты первой точки не попавшей в эту область (фигура x*x+y*y<25&&x*x+y*y>=9&
В заштрихованную фигуру бросают точки с координатами x и y. Получить координаты...

ostream &operator<< (ostream &output, const Array &obj) - что означает эта строка?
void Array::getArray() // вывод массива { for (int ix = 0; ix &lt; size;...

46
hoggy
Нарушитель
Эксперт С++
7087 / 3130 / 648
Регистрация: 15.11.2014
Сообщений: 7,209
Завершенные тесты: 1
04.08.2015, 19:50 2
Цитата Сообщение от DiffEreD Посмотреть сообщение
Ошибка для специализации: multiple definition of `void std::swap<A>(A&, A&) В чем проблема?
в main.cpp происходит инстанцирование:
void swap(A &lhs, A &rhs);

в a.cpp происходит аналогичное инстанцирование.


попробуйте вынести в a.h:
C++
1
2
3
4
5
6
7
8
9
10
namespace std
{
 
template <> inline
void swap(A &lhs, A &rhs) noexcept(noexcept(lhs.swap(rhs)))
{
    lhs.swap(rhs);
}
 
}
0
castaway
Эксперт С++
4930 / 3037 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
04.08.2015, 19:54 3
Цитата Сообщение от DiffEreD Посмотреть сообщение
multiple definition of `void std::swap<A>(A&, A&) В чем проблема?
Одна реализация генерируется <utility>, другая просто лежит в a.cpp (неиспользованная).
0
DiffEreD
1442 / 779 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
04.08.2015, 20:01  [ТС] 4
Цитата Сообщение от hoggy Посмотреть сообщение
попробуйте вынести в a.h
Тоже самое, я пробовал.
Цитата Сообщение от castaway Посмотреть сообщение
Одна реализация генерируется <utility>, другая просто лежит в a.cpp (неиспользованная).
Ну так как исправить то?
0
castaway
Эксперт С++
4930 / 3037 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
04.08.2015, 20:09 5
Цитата Сообщение от DiffEreD Посмотреть сообщение
Ну так как исправить то?
Например перенести это в main.cpp или отдельный заголовок.
C++
1
2
3
4
5
6
7
8
9
10
namespace std
{
 
template <>
void swap(A &lhs, A &rhs) noexcept(noexcept(lhs.swap(rhs)))
{
    lhs.swap(rhs);
}
 
}
И у меня еще компилятор ругается "has a different exception specifier". Компилируется так:
C++
1
2
3
4
5
template <>
void swap(A &lhs, A &rhs) noexcept(false)
{
    lhs.swap(rhs);
}
0
Eraston
59 / 11 / 3
Регистрация: 09.09.2014
Сообщений: 130
04.08.2015, 20:16 6
DiffEreD, если я правильно понял, вы пытаетесь переопределить шаблон функции из std? Вот он вам и выдает множественное определение.
0
castaway
Эксперт С++
4930 / 3037 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
04.08.2015, 20:20 7
Цитата Сообщение от Eraston Посмотреть сообщение
DiffEreD, если я правильно понял, вы пытаетесь переопределить шаблон функции из std? Вот он вам и выдает множественное определение.
Компилятор говорит о множественной реализации, а не о множественном определении.
0
Eraston
59 / 11 / 3
Регистрация: 09.09.2014
Сообщений: 130
04.08.2015, 20:28 8
DiffEreD, специализация. Ок. Попробуйте так:
Цитата Сообщение от DiffEreD Посмотреть сообщение
C++
1
2
3
4
5
template <>
void swap<A>(A &lhs, A &rhs) noexcept(noexcept(lhs.swap(rhs)))
{
    lhs.swap(rhs);
}
MSDN

Добавлено через 4 минуты

Не по теме:

Цитата Сообщение от castaway Посмотреть сообщение
Компилятор говорит о множественной реализации, а не о множественном определении.
Цитата Сообщение от DiffEreD Посмотреть сообщение
multiple definition of `void std::swap<A>(A&, A&)
транслируем: множественное определение void std::swap<A>(A&, A&), компилятор вообще может иногда сообщать немного не о том, о чем нужно

0
DiffEreD
1442 / 779 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
04.08.2015, 20:30  [ТС] 9
Цитата Сообщение от castaway Посмотреть сообщение
Например перенести это в main.cpp или отдельный заголовок.
При выносе в main работает, в отдельный заголовок - нет. Ну, а разве это правильно выносить в main?
0
castaway
04.08.2015, 20:31
  #10

Не по теме:

Цитата Сообщение от Eraston Посмотреть сообщение
транслируем
Постоянно путаю определение с объявлением.

0
DiffEreD
1442 / 779 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
04.08.2015, 20:33  [ТС] 11
Цитата Сообщение от Eraston Посмотреть сообщение
void swap<A>(A &lhs, A &rhs)
Да тоже самое
0
castaway
Эксперт С++
4930 / 3037 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
04.08.2015, 20:37 12
Лучший ответ Сообщение было отмечено DiffEreD как решение

Решение

Цитата Сообщение от DiffEreD Посмотреть сообщение
При выносе в main работает, в отдельный заголовок - нет.
a.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "a.h"
#include <utility>
#include <iostream>
 
A::A(const std::string &s) : str(s)
{}
 
void A::swap(A &other) noexcept
{
    using std::swap;
    swap(str, other.str);
 
    std::cout << "A::swap()\n";
}
a.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef A_H
#define A_H
 
#include <string>
 
class A
{
    std::string str;
public:
    A() = default;
    A(const std::string &);
 
    void swap(A &) noexcept;
};
 
#endif // A_H
b.h
C++
1
2
3
4
5
6
7
8
9
10
namespace std
{
 
template <>
void swap(A &lhs, A &rhs) noexcept(false)//noexcept(noexcept(lhs.swap(rhs)))
{
    lhs.swap(rhs);
}
 
}
main.cpp
C++
1
2
3
4
5
6
7
8
#include "a.h"
#include "b.h"
 
int main()
{
    A a1("Hello"), a2("world");
    std::swap(a1, a2);
}
У меня работает.
1
Eraston
59 / 11 / 3
Регистрация: 09.09.2014
Сообщений: 130
04.08.2015, 20:45 13
DiffEreD, пробуйте так:
C++
1
template <> void swap<A&>(A &lhs, A &rhs);
У меня без амперсанда такая же ошибка. С амперсандом жизнь прекрасна.
Ошибка компилятора C2912
0
DiffEreD
1442 / 779 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
04.08.2015, 20:48  [ТС] 14
castaway, да, и у меня тоже такой вариант заработал.
Я только спрошу - это такая общая практика реализации специализации swap для всего? В компиляторах тоже так делают?
0
castaway
Эксперт С++
4930 / 3037 / 453
Регистрация: 10.11.2010
Сообщений: 11,116
Записей в блоге: 10
Завершенные тесты: 1
04.08.2015, 20:52 15
Цитата Сообщение от DiffEreD Посмотреть сообщение
Я только спрошу - это такая общая практика реализации специализации swap для всего? В компиляторах тоже так делают?
Увы, но я любитель, про общую практику ничего сказать не могу, даже если когда-то где-то встречал.
0
DiffEreD
1442 / 779 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
04.08.2015, 20:59  [ТС] 16
Eraston, это тоже не компилируеться:
a.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
#ifndef A_H
#define A_H
 
#include <string>
 
class A
{
    std::string str;
public:
    A() = default;
    A(const std::string &);
 
    void swap(A &) noexcept;
};
 
namespace std
{
 
template <>
void swap<A&>(A &lhs, A &rhs) noexcept(noexcept(lhs.swap(rhs)))
{
    lhs.swap(rhs);
}
 
}
 
#endif // A_H
a.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include "a.h"
#include <utility>
#include <iostream>
 
A::A(const std::string &s) : str(s)
{}
 
void A::swap(A &other) noexcept
{
    using std::swap;
    swap(str, other.str);
    std::cout << "A::swap()\n";
}
main
C++
1
2
3
4
5
6
7
8
9
#include <iostream>
#include <utility>
#include "a.h"
 
int main()
{
    A a1("Hello"), a2("world");
    std::swap(a1, a2);
}


Добавлено через 5 минут
А если перенести в a.cpp, то оно даже и не вызываеться.
0
Eraston
59 / 11 / 3
Регистрация: 09.09.2014
Сообщений: 130
04.08.2015, 21:18 17
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
#ifndef gre55
#define gre55
#include <utility>
class df425
{
public:
    df425();
    ~df425();
    int l;
};
namespace std{
    template <> inline void swap<df425>(df425& a, df425& b)
    {
        printf("my swap\n");
    }
    
}
#endif
 
//... main.cpp
#include "df425.h"
//...
    df425 fggdsg, oop;
    std::swap(fggdsg,oop);
Вывел он мне-таки my swap. Фишка в очереди подключения utility видимо.

Добавлено через 5 минут
Тоже работает:
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
//df425.h
#ifndef gre55
#define gre55
#include <utility>
class df425
{
public:
    df425();
    ~df425();
    int l;
};
namespace std{
    template <> void swap<df425>(df425& a, df425& b);
}
#endif
 
//df425.cpp
#include "df425.h"
df425::df425()
{
}
df425::~df425()
{
}
namespace std{
    template <> void std::swap<df425>(df425& a, df425& b){
        printf("my swap\n");
    }
}
 
//main.cpp
#include "stdafx.h"
#include <memory>
#include <windows.h>
#include <iostream>
#include <conio.h>
#include <string>
#include "df425.h"
#pragma comment(lib,"Winmm.lib")
int main(int argc, _TCHAR* argv[])
{
    df425 fggdsg, oop;
    std::swap(fggdsg,oop);
//...
    return 0;
}
1
Tulosba
:)
Эксперт С++
4749 / 3243 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
04.08.2015, 21:27 18
Цитата Сообщение от DiffEreD Посмотреть сообщение
это такая общая практика реализации специализации swap для всего?
Используется не специализация шаблона функции, а перегрузка для класса (причем тоже шаблонная). О причинах можно почитать тут.
0
DiffEreD
1442 / 779 / 257
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
04.08.2015, 21:32  [ТС] 19
Ха, если добавить inline, то все хорошо:
a.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
#ifndef A_H
#define A_H
 
#include <iostream>
#include <string>
#include <utility>
 
class A
{
    std::string str;
public:
    A() = default;
    A(const std::string &);
 
    void swap(A &) noexcept;
};
 
namespace std
{
 
template <>
inline void swap(A &lhs, A &rhs) noexcept(noexcept(lhs.swap(rhs)))
{
    std::cout << "swap(A &lhs, A &rhs)\n";
    lhs.swap(rhs);
}
 
}
 
#endif // A_H
a.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include "a.h"
#include <utility>
#include <iostream>
 
A::A(const std::string &s) : str(s)
{}
 
void A::swap(A &other) noexcept
{
    using std::swap;
    swap(str, other.str);
    std::cout << "A::swap()\n";
}
main
C++
1
2
3
4
5
6
7
8
9
#include <iostream>
#include <utility>
#include "a.h"
 
int main()
{
    A a1("Hello"), a2("world");
    std::swap(a1, a2);
}
вывод
swap(A &lhs, A &rhs)
A::swap()
0
Eraston
59 / 11 / 3
Регистрация: 09.09.2014
Сообщений: 130
04.08.2015, 21:36 20
Цитата Сообщение от DiffEreD Посмотреть сообщение
Ха, если добавить inline, то все хорошо:
Цитата Сообщение от Eraston Посмотреть сообщение
Ошибка компилятора C2912
Там написано, почему.

Цитата Сообщение от Eraston Посмотреть сообщение
Фишка в очереди подключения utility видимо.
Нельзя создать специализацию шаблона без знания самого шаблона по магии вещей.
0
04.08.2015, 21:36
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.08.2015, 21:36

Порядок вычисления: операторы «|» и «||», «&» и «&&»
В Java булевые операторы «|» и «||», и «&amp;» и «&amp;&amp;» отличаются друг от друга...

Parse_matrix(std::istream& in); std::istream& in что это значит?
Есть функция которую необходимо описать: std::pair&lt;int, int&gt;...

Friend ostream& operator<<(ostream& stream, CArr& obj);
CArr.h #pragma once class CArr{ int* arr = nullptr; int size = 10; void...


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

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

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