【发布时间】:2020-11-13 01:26:51
【问题描述】:
问题
给定以下代码:
template <typename T>
struct dummy {
enum enumenum { a = 1, b = 2, c = 4 };
};
int main() {
// I want this line to expands as :
// dummy<double>::enumenum a = operator~(dummy<double>::a);
auto a = ~dummy<double>::a;
}
如何在 enumenum 上重载运算符?
我正在使用标准 C++14。
我尝试了什么
一个简单的实现:
template <typename T>
typename dummy<T>::enumenum
operator~(typename dummy<T>::enumenum a) {
return static_cast<typename dummy<T>::enumenum>(operator~(a));
}
不幸的是,有问题的行扩展为:
int a = ~static_cast<int>(dummy<double>::a);
这意味着未使用该运算符(这是默认行为)。
是不是因为 ADL 在 struct 命名空间中找不到正确的operator~()(这甚至是一件事吗?)?
然后我尝试了:(注意friend)
template <typename T>
struct dummy {
enum enumenum { a, b, c };
friend enumenum operator~(enumenum a) {
return static_cast<enumenum>(~a);
}
};
这实际上工作并扩展为:
template <>
struct dummy<double> {
enum enumenum {
a = static_cast<unsigned int>(1),
b = static_cast<unsigned int>(2),
c = static_cast<unsigned int>(4)
};
friend inline dummy<double>::enumenum operator~(dummy<double>::enumenum a) {
return static_cast<dummy<double>::enumenum>(operator~(a));
}
};
int main()
{
dummy<double>::enumenum a = operator~(dummy<double>::a);
}
这是我想要的行为。除了,如果我不想在类主体中定义运算符怎么办。
所以我尝试了:
template <typename T>
struct dummy {
enum enumenum { a = 1, b = 2, c = 4 };
// if inline : inline function 'operator~' is not defined [-Wundefined-inline]
// and adding inline to the template below does not help
friend enumenum operator~(enumenum a);
};
template <typename T>
typename dummy<T>::enumenum
operator~(typename dummy<T>::enumenum a) {
return static_cast<typename dummy<T>::enumenum>(~a);
}
int main() {
auto a = ~dummy<double>::a;
}
上面的代码展开为:
template<>
struct dummy<double>
{
enum enumenum
{
a = static_cast<unsigned int>(1),
b = static_cast<unsigned int>(2),
c = static_cast<unsigned int>(4)
};
friend dummy<double>::enumenum operator~(dummy<double>::enumenum a);
};
int main()
{
dummy<double>::enumenum a = operator~(dummy<double>::a);
}
这可以编译,但不链接! 编辑:我相信它不会链接,因为模板没有被实例化,因此在链接时失败(类似于上面的幼稚实现)。
结论
即使我以某种方式找到了实现我想要的方法,但如果我不想在类定义中定义运算符。
提前致谢。
【问题讨论】:
-
请务必在问题中包含错误消息。上一个版本在这里编译(和链接)很好:godbolt.org/z/oW7TY5 您是否将运算符的定义放在源文件中?另外我不明白“此代码扩展为”是什么意思
-
我也在使用编译器资源管理器:godbolt.org/z/87a149,我收到以下错误:未定义对 `operator~(dummy
::enumenum)' clang-10 的引用:错误:链接器命令退出代码失败 1. 编辑:我相信您没有收到链接错误的原因是您给我的链接 (godbolt.org/z/oW7TY5) 没有使用“编译为二进制”选项或“运行编译后的输出”选项”。因此它不会运行链接器。 -
如果我不想在类主体中定义运算符怎么办 - 在任何情况下,这似乎都是最优雅的解决方案。为什么不? (经过多次修补后无法解决您的问题)。
-
如果是风格问题,您始终可以调用友元定义中其他地方定义的方法(尽管您可能需要添加一些前向声明)。附:如果您使用
template <typename T> T operator~(T a),naive 实现可以工作,但我找不到检查T是否属于dummy<U>::enumenum类型的一些U。
标签: c++ templates operator-overloading c++14 friend-function