gpt4 book ai didi

c++ - 使用继承的成员运算符而不是免费的

转载 作者:塔克拉玛干 更新时间:2023-11-03 06:41:56 25 4
gpt4 key购买 nike

假设在命名空间 ns 的某处定义了一个免费的 operator*:

namespace ns {
struct Dummy {};

template <typename T>
Dummy operator*(T&&) {
return {};
}
}

在不同的地方,同一个命名空间中有一个基类,它定义了成员operator*:

namespace ns {
template <typename T>
struct Base {
T x;

T& operator*() {
return x;
}
};
}

并且派生出很多类型。它们的行为相同,但必须不同,因为其他地方的模板需要专门针对它们:

namespace ns {
template <typename T>
struct DerivedA : Base<T> {};

template <typename T>
struct DerivedB : Base<T> {};

template <typename T>
struct DerivedC : Base<T> {};

// etc
}

当我尝试在派生类上使用 operator* 时:

ns::DerivedA<int> d;
*d = 42;

GCC 对我大喊“傻瓜!你不能将 int 分配给 Dummy!”,这显然意味着免费的 operator* 是用于代替基类中的成员一。

我完全无法控制 free 运算符,也无法将派生类移动到不同的命名空间。

如何在不在每个派生类中复制 operator* 的情况下解决这个问题?

最佳答案

简短的回答,你可以这样做:

template <typename T>
struct DerivedA : Base<T> {
using Base<T>::operator*;
};

长答案:为了弄清楚 *d 调用什么,我们必须确定所有可行的函数(§13.3.2):

From the set of candidate functions constructed for a given context (13.3.1), a set of viable functions is chosen, from which the best function will be selected by comparing argument conversion sequences for the best fit (13.3.3). The selection of viable functions considers relationships between arguments and function parameters other than the ranking of conversion sequences.

有两个:

template <typename T>
Dummy operator*(T&& );

T& Base::operator*();

为了弄清楚选择哪个,我们必须确定哪个“隐式转换序列”(§13.3.3.1)更好:

An implicit conversion sequence is a sequence of conversions used to convert an argument in a function call to the type of the corresponding parameter of the function being called.

我们的第一个选项是“精确匹配”,而我们的第二个重载选项是 (§13.3.3.1.6):

When the parameter has a class type and the argument expression has a derived class type, the implicit conversion sequence is a derived-to-base Conversion from the derived class to the base class. [ Note: There is no such standard conversion; this derived-to-base Conversion exists only in the description of implicit conversion sequences. —end note ] A derived-to-base Conversion has Conversion rank

转换序列的排名是(§13.3.3.1.1.3):

Each conversion in Table 12 also has an associated rank (Exact Match, Promotion, or Conversion). These are used to rank standard conversion sequences (13.3.3.2). The rank of a conversion sequence is determined by considering the rank of each conversion in the sequence and the rank of any reference binding (13.3.3.1.4). If any of those has Conversion rank, the sequence has Conversion rank; otherwise, if any of those has Promotion rank, the sequence has Promotion rank; otherwise, the sequence has Exact Match rank.

我不知道如何在这里插入表格。但基本上我们有一个“精确匹配”(调用 Dummy operator*(T&&))和一个“转换”(调用 T& Base::operator*),因此“精确匹配”是“最佳可行功能”。并且(§13.3.3.2):

If there is exactly one viable function that is a better function than all other viable functions, then it is the one selected by overload resolution

这就是为什么首选 Dummy operator*(T&& ) 的原因。

现在,为什么我的建议有效?在这种情况下,我们的两个选择是:

template <typename T>
Dummy operator*(T&& );

T& DerivedA<int>::operator*();

因此我们有两个“完全匹配”候选者 - 尽管其中一个是通过模板并且选择更好的可行函数的标准之一是 (§13.3.3.1):

Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if ...

  • F1 is a non-template function and F2 is a function template specialization

因此,在这种情况下,我们选择 DerivedA::operator*。这就是你想要的。

关于c++ - 使用继承的成员运算符而不是免费的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27078793/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com