ADL应该如何工作
How should ADL work for this?
最近,我遇到了clang++5.0.0编译器的一个问题,通过ADL,它没有在Mac上获得正确的函数(但g++在Linux上做得正确)。我想知道这是编译器问题还是一般的类设计不好
下面是一个示例代码(纯粹用于说明目的):
namespace test {
class Ops {
public:
Ops():val_(0){}
template<typename T>
Ops& operator<< (const T& val) {
std::cout << "Called member function" << std::endl;
this->val_ = val;
return *this;
}
private:
int val_;
};
template<typename T>
struct Any {
T val_;
};
template <template<typename> class E, typename T>
Ops& operator<< (Ops& op, const E<T>& val) {
std::cout << "Global function" << std::endl;
return op;
}
}
int main() {
test::Ops op;
int k = 9;
test::Any<int> a;
op << a;
return 0;
}
我想知道ADL和模板论点推导将如何以循序渐进的方式找到最佳匹配
对于同一个"主体",是否有任何情况下会首选成员功能来代替自由功能?(这就是产品构建中发生的情况)
提前谢谢。
这是详细发生的事情,也是每个编译器应该做的事情:通过限定查找找到候选模板函数
template <typename T>
test::Ops::operator<<(const T&)
而第二候选是通过ADL使用模板参数推导(cfr.temp.dexeract.conv)生成的
template <template <typename> class E, typename T>
test::operator<<(test::Ops&, const E<T>&)
之后,过载解决方案开始生效(参见13.3.3),由于,非成员(F1)优先于成员(F2)
- F1和F2是函数模板专业化,F1的函数模板更专业而不是根据14.5.6.2中描述的偏序规则的F2的模板
从而被选择为要调用的函数。
回答您的问题:这取决于过载解决规则。作为成员函数或在内部范围内不会影响结果和之类的东西
namespace test {
class Ops {
public:
Ops():val_(0){}
template<typename T>
Ops& operator<< (const T& val) {
std::cout << "Called member function" << std::endl;
this->val_ = val;
return *this;
}
private:
int val_;
};
template<typename T>
struct Any {
T val_;
};
template <typename E>
Ops& operator<< (Ops& op, const E& val) {
std::cout << "Global function" << std::endl;
return op;
}
}
只会触发过载解析错误"use of overloaded operator '<<' is ambiguous
"。
另外:即使选择了成员函数,它也是错误的:this->val
被分配了一个非整数类型。
这两个候选函数在重载集中:
// member function template, found by qualified lookup
template <typename T>
test::Ops::operator<<(const T&)
// non-member function template, found by ADL
template <template <typename> class E, typename T>
test::operator<<(test::Ops&, const E<T>&)
在运算符查找中,没有对成员和非成员进行优先选择。在模板参数替换之后,两个函数模板专门化与所提供的参数类型完全匹配(具有限定转换)。但取E<T>
的函数比取T
的函数更专业,因此选择非成员函数是出于这个原因。
Apple clang 5.0.0基于LLVM clang 3.3svn。我找不到任何选择成员函数的LLVM claang版本。这可能是苹果代码中的一个错误,但IMHO,这更有可能是你实际编译的代码或你的环境中的一些细微差异。您是否尝试过使用可疑的编译器编译示例代码?
- QSqlquery prepare()和bindvalue()不工作
- 导入库可以跨dll版本工作吗
- 以螺旋方式打印矩阵的程序.(工作不好)
- 对象指针在c++中是如何工作的
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- VSOMEIP-2个设备之间的通信(TCP/UDP)不工作
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- C++为线程工作动态地分割例程
- 为什么我的 std::ref 无法按预期工作?
- 布尔比较运算符是如何在C++中工作的
- SampleConsensusPrerejective(ext.RANSAC)是如何真正工作的
- 不确定要在我的main中放入什么才能使我的代码正常工作
- 为什么std::condition_variable notify_all的工作速度比notify_one快(对于随机请
- <<操作员在下面的行中工作
- 有人能解释一下为什么下界是这样工作的吗C++的
- ExtractIconEx:可以工作,但偶尔会崩溃
- C++中的memset函数工作不正常
- 当我在第一个循环中使用"auto"时,它工作正常,但是使用"int"它会给出错误,为什么?
- 当 int 方法工作正常时,void 方法有何不同,或者为什么我不能调用 void 方法?
- sdl软件渲染器不工作,工作在硬件加速的一个