使用模板重载运算符,但阻止重定义
Overload operator with template, but prevent redefinition
我想使用模板定义operator<<
的专用化,但如果已经为某些数据类型定义了该运算符,我不希望它破坏该运算符的行为。
enum State {Open, Locked};
enum Input {Coin, Push};
std::string ToString(State c){
switch (c) {
case Locked : return "Locked";
case Open : return "Open";
}
}
std::string ToString(Input c){
switch (c) {
case Coin : return "Coin";
case Push : return "Push";
}
}
template<typename T> //obviously, a bad idea
std::ostream& operator<<(std::ostream& s, T c) {
return s<<ToString(c);
}
稍后在代码中我想使用:
int main() {
std::cout<<Coin<<std::endl;
std::cout<<Open<<std::endl;
std::cout<<std::string("normal string")<<std::endl;
}
不出所料,上面给出了编译错误:
error: ambiguous overload for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream<char>}’ and ‘std::string {aka std::basic_string<char>}’)
std::cout<<std::string("normal string")<<std::endl;
(更多关注(
问:如果函数/运算符已经有定义,如何告诉编译器忽略模板?
您可以使用 SFINAE 使模板实例化仅对ToString()
重载支持的类型有效,例如
template<typename T, typename = decltype(ToString(std::declval<T>()))>
std::ostream& operator<<(std::ostream& s, T c) {
return s<<ToString(c);
}
住
要补充@songyuanyao回答的内容,请再做两件事:
- 将代码包装在命名空间中。 通过
- 命名空间
decltype
完全限定标识符。 即类似decltype(MyNS::ToString(std::declval<T>()))
.
由于 ADL,您的打印语句仍然可以工作,但是如果您的运算符在某种程度上是具有在另一个命名空间中定义ToString
类型的候选项,则不会违反查找规则。1
1如果您的命名空间中有任何模板,则 ADL 也会考虑其参数的命名空间。这可能会使您在非限定查找期间受到另一个ToString
定义的摆布。
我发现我可以使用C++概念来做到这一点
template<typename T>
concept bool HasToString = requires(T a) {
{ ToString(a) } -> std::string;
};
std::ostream& operator<<(std::ostream& s, HasToString c) {
return s<<ToString(c);
}
这需要gcc.6和-fconcepts
编译标志。
相关文章:
- 在 C++ 的自定义运算符中删除与删除[](不同于常见的删除与删除[]问题)
- 自定义运算符重载C++,无开销
- 如何为缺少预定义运算符而不扩展命名空间"std"的标准类型定义运算符>> (istream &, ...)?
- 如何使用C++将MXNET自定义运算符构建到单独的库/包中?
- 模板类的用户定义运算符上的 C++ 隐式转换
- 什么是编程语言支持定义您自己的自定义运算符?
- 如何在Qt中为矩阵类定义[ ][ ]运算符?
- 在 c++ 迭代器中,我应该同时定义运算符== 和运算符!=吗?
- 在 rxcpp 中创建自定义运算符
- 错误 C2676;在C++的二叉搜索树类中定义 ++ 运算符时遇到问题
- std::map :使用自定义运算符时更新密钥
- 最初定义运算符C++在哪里
- 如何在Tensorflow Lite中添加自定义运算符
- 如何在 rxcpp 自定义运算符中正确推断泛型
- 在模板化类之外定义运算符重载
- 为类定义之外的模板类定义运算符[]()(数组订阅)
- 是否可以在类定义之外定义运算符[]()(数组订阅)
- C++ 重新定义运算符<() 和运算符!=()
- 如何将上下文信息传递给自定义运算符<<适用于 std::iostream
- 无法在C++中定义++运算符,这里有什么问题?