假设我们在自定义类上有operator/
:
struct my_class {
uint64_t value;
}
template<class T>
constexpr T operator/(const my_class& a, const my_class& b)
{
return static_cast<T>(a.value) / static_cast<T>(b.value);
}
如何选择a / b
(其中a
和b
属于my_class
类型)返回int
或double
,例如?
答案 0 :(得分:5)
您可以使用一些模板魔术和转换运算符。您可以先为表达式定义一个简单的包装器:
SELECT t1.IDtag,
t1.Name,
GROUP_CONCAT(COALESCE(t2.Record, 'no rap sheet'))
FROM Table1 t1
LEFT JOIN Table2 t2
ON t1.IDtag = t2.IDtag
GROUP BY t1.IDtag
然后,可以像这样重载运算符:
struct DivideMyClass {
DivideMyClass(const MyClass& lhs_, const MyClass& rhs_) : lhs{lhs_}, rhs_{rhs} {}
template<typename T>
operator T () const {
return static_cast<T>(lhs.value) / static_cast<T>(rhs.value);
}
private:
const MyClass& lhs;
const MyClass& rhs;
};
然后您的代码将如下所示:
constexpr DivideMyClass operator/(const my_class& a, const my_class& b)
{
return DivideMyClass{a, b};
}
语言不会通过返回类型重载除法。你的代码会混淆其他思维,这是一个错误。如果你广泛使用这种方法,你最终会得到一个令人难以理解的代码。
另一方面,转换是隐含的,并且没有任何内容表明在呼叫站点的运营商中是否确实进行了转换。
您将阻止AAA idom(几乎总是使用自动)。 double d = MyClass{21} / MyClass{5}; // will be equal to 4.2
可能会破坏您的代码,这是一件坏事。
这样的技术应该用于模板表达和类似的东西。使用它进行简单的划分会使其他人感到困惑。
答案 1 :(得分:3)
我可以根据接受结果的变量类型进行选择吗?即INT result = a / b返回int,但是double result = a / b返回double?
如果你一心想做到这一点你可以,但它很复杂,我不会推荐它。你必须仔细权衡利益与引入的复杂性。你可以通过懒惰的评估来做到这一点:
struct X {
int value;
};
struct X_op_proxy {
const X& lhs;
const X& rhs;
template <class T>
operator T() const { return static_cast<T>(lhs.value) / static_cast<T>(rhs.value); }
};
auto operator/(const X& lhs, const X& rhs) -> X_op_proxy
{
return {lhs, rhs};
}
int main()
{
X x1{11}, x2{2};
int i = x1 / x2;
cout << i << endl;
float f = x1 / x2;
cout << f << endl;
}
这是最低限度,因此您可以弄清楚这项技术的用途。您可以根据自己的需要调整并发展它。
答案 2 :(得分:2)
要选择特定的操作员模板,您必须将其称为功能:
auto result = operator/<double>(my_class{4}, my_class{2});
// result is 2.0