c – std ::与G交换奇怪
这是一个奇怪的地方,我不知道,如果它是C标准,我的编译器(G版本4.6.3在Ubuntu 12.04,这是最新的长期支持版本的Ubuntu)或与我,谁不明白;-)
该代码简单如下: #include <algorithm> // for std::swap void f(void) { class MyClass { }; MyClass aa,bb; std::swap(aa,bb); // doesn't compile } 当使用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]) 令人惊讶的结果是,只需将类定义从函数中移出即可使代码编译正确: #include <algorithm> // for std::swap class MyClass { }; void f(void) { MyClass aa,bb); // compiles fine! } 那么,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); // compiles fine! } 但是只需从对象更改为指针,然后编译再次失败: #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! } 当然,在我的实际应用中,课程更复杂;我尽可能简化了代码,仍然可以重现问题. 解决方法
如果您以C 03模式运行,我认为是这样,您不能在模板中使用本地定义的类型.如果是这种情况,您可以在命名空间级别定义类型,使其工作,否则可以在C11模式下进行编译.[*]
如果您想知道为什么第二种情况可行,该标准不提供专业化 template <typename T> void swap(T&,T&) // [1] 因为std :: list是一个模板本身,你不能部分地专门化模板函数.它提供了一个不同的基本模板: template <typename T,typename A> void swap(list<T,A>&,list<T,A>&); // [2] 现在如前所述,编译器不能使用[1]的本地类型,因此被丢弃.然后它尝试[2],它发现它可以将本地类型的左值转换为引用到基础std :: list< int>,之后转换[2]是一个很好的候选者.然后会打电话 std::swap(static_cast<std::list<int&>>(aa),static_cast<std::list<int&>>(bb)); 它不使用本地类型,而是命名空间级别std :: list< int> ;. 另一方面,它编译的事实并不意味着它会执行你想要的.特别地,如果扩展类型MyListClass添加了任何新的成员变量,那么它们将不被替换. 所有这一切,就像旁注:你不应该从标准容器继承,因为它们从来没有被设计为继承. [*]免责声明:我不知道在特定版本的编译器中是否支持此功能,您将不得不仔细检查. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- c# – Winforms控件中的阴影?
- 如何配置FlashDevelop软件并支持Flash CS4[转]
- 2. PRXPARSE () | 正则表达式的“阿赖耶识”
- ruby-on-rails – 如何在rails 4中组织控制器目录而不会弄乱
- c – 基类中的析构函数何时和为什么不被定义为虚拟的?
- .net – 如何禁止此COM泛型警告?
- c# – 在RavenDb中引用值对象父实体对象
- webpack构建多页面react项目(webpack+typescript+react)
- vb.net – 如何使用json到linq在json.net中创建字典结构
- Oracle 11g第1版与第2版 – LEFT OUTER JOIN的不同行为