我尝试在GoingNative在他的谈话肖恩家长提供的代码2013 - "Inheritance is the base class of evil".(代码提供的最后一张幻灯片在https://gist.github.com/berkus/7041546为什么编译器在这种情况下选择不正确的函数重载?
我试图实现我自己同样的目标,但我可以”不懂为什么,因为我期望它下面的代码不会采取行动。
#include <boost/smart_ptr.hpp>
#include <iostream>
#include <ostream>
template <typename T>
void draw(const T& t, std::ostream& out)
{
std::cout << "Template version" << '\n';
out << t << '\n';
}
class object_t
{
public:
template <typename T>
explicit object_t (T rhs) : self(new model<T>(rhs)) {};
friend void draw(const object_t& obj, std::ostream& out)
{
obj.self->draw(out);
}
private:
struct concept_t
{
virtual ~concept_t() {};
virtual void draw(std::ostream&) const = 0;
};
template <typename T>
struct model : concept_t
{
model(T rhs) : data(rhs) {};
void draw(std::ostream& out) const
{
::draw(data, out);
}
T data;
};
boost::scoped_ptr<concept_t> self;
};
class MyClass {};
void draw(const MyClass&, std::ostream& out)
{
std::cout << "MyClass version" << '\n';
out << "MyClass" << '\n';
}
int main()
{
object_t first(1);
draw(first, std::cout);
const object_t second((MyClass()));
draw(second, std::cout);
return 0;
}
此版本处理打印int
罚款,但未能在第二种情况下进行编译,因为编译器不知道如何使用MyClass
与operator<<
。我不明白为什么编译器不会选择专门为第二个过载提供的e MyClass
。如果我更改model :: draw()方法的名称并从其主体中删除全局名称空间说明符,或者如果将MyClass的draw全局函数更改为完整的模板专用化,则代码编译并正常工作。
该错误消息我得到的是如下,之后是candidate function not viable...
t76_stack_friend_fcn_visibility.cpp:9:9: error: invalid operands to binary expression ('std::ostream' (aka 'basic_ostream<char>') and 'const MyClass')
out << t << '\n';
~~~^~
t76_stack_friend_fcn_visibility.cpp:36:15: note: in instantiation of function template specialization 'draw<MyClass>' requested here
::draw(data, out);
^
t76_stack_friend_fcn_visibility.cpp:33:9: note: in instantiation of member function 'object_t::model<MyClass>::draw' requested here
model(T rhs) : data(rhs) {};
^
t76_stack_friend_fcn_visibility.cpp:16:42: note: in instantiation of member function 'object_t::model<MyClass>::model' requested here
explicit object_t (T rhs) : self(new model<T>(rhs)) {};
^
t76_stack_friend_fcn_visibility.cpp:58:20: note: in instantiation of function template specialization 'object_t::object_t<MyClass>' requested here
const object_t second((MyClass()));
^
一堆为什么全球绘制模板功能模板版本choosen在MyClass的函数重载?是否因为模板引用是贪婪的?如何解决这个问题?
我试过你用MSVC13的代码,它编译得很好,在第一种情况下使用int版本,在第二种情况下使用int版本。你应该添加关于你使用的编译器 – Christophe 2014-11-08 20:50:58
我使用ng --version ng版本3.5.0(tags/RELEASE_350/final)。 – 2014-11-08 20:56:42
[另一个问题具有相同的原理](http://stackoverflow.com/questions/8501294/different-behavior-for-qualified-and-unqualified-name-lookup-for-template/8501421#8501421) – 2014-11-10 02:30:16