考虑以下类型特征:
template
struct has_begin : std::false_type {};
template
struct has_begin>()))
>> : std::true_type {};
为什么此特征不考虑我的用户定义的重载std::begin
?
namespace std {
void begin(foo&) {}
}
int main() {
static_assert(has_begin::value); // Fails.
foo f;
std::begin(f); // Works.
}
现场例子
有趣的观察:
如果我更改此类型特征的顺序和我的重载,它将起作用
如果我在特征类型中使用ADL:
decltype(std::begin(std::add_lva... -> decltype(begin(std::add_lva...
如果free函数begin
与foo位于相同的名称空间中,则它可以工作:
void begin(foo) { }
但是对于std ::之外的任何类都失败,具体取决于:
void begin(foo) { }
因为ADL查找不适用于其他名称空间的模板。
std::begin(foo&)
在不更改包含顺序的情况下,我可以做些什么来支持我的类型特征?
否则,我必须同时支持这两个世界-为std :: begin和ADL begin()编写类型特征。
在我的函数中,我已经做了这样的事情(建议在这里):
auto get_begin() { using std::begin; return begin(object); }
Nicol Bolas.. 6
在不更改包含顺序的情况下,我该怎么做才能在其类型特征中支持std :: begin(foo&)?
你不 std::begin
并不意味着直接为任意范围调用。如果要访问begin/end
范围类型,则应结合使用ADL和ADL using std::begin/end
。这就是成语在C ++中的工作方式。
重载std
名称空间中的方法是非法的,std::begin
也不例外。您可以创建std
-defined模板的模板专业化(基于用户创建的类型),但这不是使用C ++习惯用法的正确方法。
在C ++ 20中,该std::ranges::begin
函数应直接调用,而针对类型专门化该函数的方法是通过ADL或成员begin
函数。因此,只要使用该成语,每个人都会没事的。
在不更改包含顺序的情况下,我该怎么做才能在其类型特征中支持std :: begin(foo&)?
你不 std::begin
并不意味着直接为任意范围调用。如果要访问begin/end
范围类型,则应结合使用ADL和ADL using std::begin/end
。这就是成语在C ++中的工作方式。
重载std
名称空间中的方法是非法的,std::begin
也不例外。您可以创建std
-defined模板的模板专业化(基于用户创建的类型),但这不是使用C ++习惯用法的正确方法。
在C ++ 20中,该std::ranges::begin
函数应直接调用,而针对类型专门化该函数的方法是通过ADL或成员begin
函数。因此,只要使用该成语,每个人都会没事的。