Как исправить ошибку компиляции с gcc8 при специализированной функции подкачки / - PullRequest
1 голос
/ 26 сентября 2019

Я пытаюсь скомпилировать код, который специализирует функцию std :: swap для моего класса.Но я сталкиваюсь с проблемой, которая возникает из-за конструктора rvalue (он работает, когда я комментирую строку)

Я компилирую с g ++ (GCC) 8.2.1 20180905 (Red Hat 8.2.1-3) иg ++ -std = c ++ 14 -Все эти опции

#include <iostream>
#include <utility>

namespace ns1
{
class Foo 
{
public:
    Foo();
    Foo(const Foo& that) {};
    Foo(Foo&& that) {};  // <--- work when commented
    ~Foo();  
    void swap(Foo &that) {};
};

inline void swap(Foo &lhs, Foo &rhs)
{
   lhs.swap(rhs);
}
}  // namespace ns1

namespace std {

template <>
inline void swap(ns1::Foo &lhs, ns1::Foo &rhs)
{
   lhs.swap(rhs);
}

} // namespace std

У меня появляется следующее сообщение об ошибке:

 error: template-id 'swap<>' for 'void std::swap(ns1::Foo&, ns1::Foo&)' does not match any template declaration
 inline void swap(ns1::Foo &lhs, ns1::Foo &rhs)
             ^~~~
In file included from /opt/rh/devtoolset-8/root/usr/include/c++/8/string:52,
                 from /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/locale_classes.h:40,
                 from /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/ios_base.h:41,
                 from /opt/rh/devtoolset-8/root/usr/include/c++/8/ios:42,
                 from /opt/rh/devtoolset-8/root/usr/include/c++/8/ostream:38,
                 from /opt/rh/devtoolset-8/root/usr/include/c++/8/iostream:39,
                 from toto.cpp:1:
/opt/rh/devtoolset-8/root/usr/include/c++/8/bits/basic_string.h:6276:5: note: candidates are: 'template<class _CharT, class _Traits, class _Alloc> void std::swap(std::basic_string<_CharT, _Traits, _Alloc>&, std::basic_string<_CharT, _Traits, _Alloc>&)'
     swap(basic_string<_CharT, _Traits, _Alloc>& __lhs,
     ^~~~
In file included from /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/stl_algobase.h:64,
                 from /opt/rh/devtoolset-8/root/usr/include/c++/8/bits/char_traits.h:39,
                 from /opt/rh/devtoolset-8/root/usr/include/c++/8/ios:40,
                 from /opt/rh/devtoolset-8/root/usr/include/c++/8/ostream:38,
                 from /opt/rh/devtoolset-8/root/usr/include/c++/8/iostream:39,
                 from toto.cpp:1:

Ответы [ 2 ]

1 голос
/ 26 сентября 2019

Ошибка, которую вы видите, заключается в том, что предоставление пользовательского конструктора перемещения не позволяет компилятору синтезировать оператор перемещения-назначения, что делает ваш класс не назначаемым-перемещением.Согласно cppreferece , T в swap должно быть назначено перемещение.

Чтобы исправить это, предоставьте также оператор назначения перемещения, demo

Foo& operator=(Foo&& other) {return *this;}
Foo& operator= (const Foo& other) { return *this; }

Также взгляните на правило пяти

0 голосов
/ 26 сентября 2019

Может быть, вместо расширения std было бы лучше положиться на ADL + using std::swap;.
Ваш пример очень похож на это руководство.
(http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c165-use-using-for-customization-points)

Другое руководство говоритчто мы должны предпочесть перегрузку шаблонной специализации
(http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#t144-dont-specialize-function-templates)
, но, к сожалению, это неопределенное поведение в std
(https://en.cppreference.com/w/cpp/language/extending_std)

...