1

I'm trying to compile code which specialize the function std::swap for my class. But I'm facing an issue that occurs because of rvalue constructor (it works when I comment the line)

I am compiling with g++ (GCC) 8.2.1 20180905 (Red Hat 8.2.1-3) and g++ -std=c++14 -Wall those options

#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

I have the following error message :

 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:
4

2 回答 2

1

您看到的错误是因为提供用户定义的移动构造函数会阻止编译器合成移动赋值运算符,从而使您的类不可移动赋值。根据cpprefereceTinswap必须是可移动分配的。

要修复它,请同时提供移动赋值运算符,演示

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

也看看五法则

于 2019-09-26T15:59:03.953 回答
0

也许依赖 ADL+ 而不是扩展std它应该更好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

于 2019-09-26T15:51:57.320 回答