4
我有一些代码,很简单,看起来有点像这样:暧昧运营商<<选择
#include <iostream>
#include <type_traits>
namespace X {
struct Foo {int x;};
struct Bar {int x;};
template <typename T , typename = typename std::enable_if<
std::is_same<decltype(T::x),int>::value
>::type>
std::ostream & operator<<(std::ostream & os, const T&) {
return os;
}
}
namespace Y {
struct Faa : X::Foo {int y;};
struct Baz {int x; int y;};
template <typename T , typename = typename std::enable_if<
std::is_same<decltype(T::x),int>::value &&
std::is_same<decltype(T::y),int>::value
>::type>
std::ostream & operator<<(std::ostream & os, const T&) {
return os;
}
}
int main() {
// Everything is ok
X::Foo x;
std::cout << x;
Y::Baz k;
std::cout << k;
// Problems..
Y::Faa y;
// std::cout << y; // <--operator is ambiguous
Y::operator<<(std::cout, y);
return 0;
}
有什么办法避免模棱两可的运营商Y::Faa
,并具有手动指定Y::operator<<
?如果不是,为什么?
通过'enable_if'所施加的限制似乎很微弱(种类太多被允许)。你可以改进它们吗?通过使用类型特质? – dyp 2014-09-23 14:27:16
在我的实际代码中,我做了一个检查各种成员方法存在的实际特征,但这个想法是相同的。尽管如此,我认为这还不算什么问题。 – Svalorzen 2014-09-23 14:39:31
我宁愿想像某种允许类型的列表;可以让你“确定”哪些类型是(作为)命名空间的直接成员。从这些,你可以选择那些名为'x'的成员。 – dyp 2014-09-23 14:43:37