Kai*_*zke 10 c++ swap compiler-errors std
这是一个奇怪的,我不知道,如果它是C++标准,我的编译器(Ubuntu 12.04上的G ++版本4.6.3,这是Ubuntu的最新长期支持版本)或我,谁不明白;-)
有问题的代码简单如下:
#include <algorithm> // for std::swap
void f(void)
{
class MyClass { };
MyClass aa, bb;
std::swap(aa, bb); // doesn't compile
}
Run Code Online (Sandbox Code Playgroud)
尝试使用G ++编译时,编译器会产生以下错误消息:
test.cpp: In function ‘void f()’:
test.cpp:6:21: error: no matching function for call to ‘swap(f()::MyClass&, f()::MyClass&)’
test.cpp:6:21: note: candidates are:
/usr/include/c++/4.6/bits/move.h:122:5: note: template<class _Tp> void std::swap(_Tp&, _Tp&)
/usr/include/c++/4.6/bits/move.h:136:5: note: template<class _Tp, long unsigned int _Nm> void std::swap(_Tp (&)[_Nm], _Tp (&)[_Nm])
Run Code Online (Sandbox Code Playgroud)
令人惊讶的结果是,只是将类定义移出函数使得代码编译正常:
#include <algorithm> // for std::swap
class MyClass { };
void f(void)
{
MyClass aa, bb;
std::swap(aa, bb); // compiles fine!
}
Run Code Online (Sandbox Code Playgroud)
那么,std :: swap()不应该在类上工作,这些类是函数私有的吗?或者这是G ++的一个错误,也许是我正在使用的G ++的特定版本?
更令人费解的是,尽管MyListClass也是私有的(但是扩展了一个"官方"类,其中可能存在swap()的特定实现),以下内容确实再次起作用:
#include <algorithm> // for std::swap
#include <list> // for std::list
void g(void)
{
class MyListClass : public std::list<int> { };
MyListClass aa, bb;
std::swap(aa, bb); // compiles fine!
}
Run Code Online (Sandbox Code Playgroud)
但只是从对象更改为指针,再次编译失败:
#include <algorithm> // for std::swap
#include <list> // for std::list
void g(void)
{
class MyListClass : public std::list<int> { };
MyListClass aa, bb;
MyListClass* aap = &aa;
MyListClass* bbp = &bb;
std::swap(aap, bbp); // doesn't compile!
}
Run Code Online (Sandbox Code Playgroud)
当然,在我的实际应用中,类更复杂; 我尽可能地简化代码以仍然重现问题.
Dav*_*eas 16
如果您在C++ 03模式下运行(我认为是这种情况),则不允许在模板中使用本地定义的类型.如果是这种情况,您可以在命名空间级别定义类型以使其工作,否则您可以在C++ 11模式下编译它应该编译.[*]
如果你想知道为什么第二种情况有效,标准不提供专业化
template <typename T> void swap(T&,T&) // [1]
Run Code Online (Sandbox Code Playgroud)
作为std::list模板本身,您不能部分专门化模板功能.它提供的是一个不同的基本模板:
template <typename T, typename A> void swap(list<T,A>&,list<T,A>&); // [2]
Run Code Online (Sandbox Code Playgroud)
现在和前面的情况一样,编译器不能将本地类型与[1]一起使用,因此会被丢弃.然后它尝试[2],它发现它可以将本地类型的左值转换为对基数的引用std::list<int>,之后转换[2]是一个很好的候选者.然后它会打电话
std::swap(static_cast<std::list<int&>>(aa),static_cast<std::list<int&>>(bb));
Run Code Online (Sandbox Code Playgroud)
它不使用本地类型,而是使用名称空间级别 std::list<int>.
另一方面,它编译的事实并不意味着它做你想要的.特别是,如果扩展类型MyListClass添加任何新成员变量,则不会交换这些变量.
所有这些,只是作为旁注:你不应该继承标准容器,因为它们从来没有被设计为继承.
[*]免责声明:我不知道在特定版本的编译器中是否支持此功能,您必须仔细检查.
| 归档时间: |
|
| 查看次数: |
2438 次 |
| 最近记录: |