gpt4 book ai didi

c++ - SFINAEd-out 函数是否隐藏了从基类显式导入的重载

转载 作者:可可西里 更新时间:2023-11-01 15:17:37 28 4
gpt4 key购买 nike

在遇到另一个设计问题后,我决定制作一个包装类,当且仅当基类中尚不存在可行的重载时,才能向基类的某些成员函数添加重载。基本上,这就是我想要做的:

template<typename T>
struct wrapper: T
{
using T::foo;

template<typename Arg>
auto foo(Arg) const
-> std::enable_if_t<not std::is_constructible<Arg>::value, bool>
{
return false;
}
};

struct bar
{
template<typename Arg>
auto foo(Arg) const
-> bool
{
return true;
}
};

在这个简单的例子中,wrapper添加一个重载的 foo仅当来自基类的那个不可行时(我将 std::enable_if 简化为可能的最简单的东西;最初的一个涉及检测成语)。但是,g++ 和 clang++ 不同意。接下main :

int main()
{
assert(wrapper<bar>{}.foo(0));
}

g++ 没问题:foo来自 wrapper<bar>是 SFINAEd,所以它使用来自 bar 的那个反而。另一方面,clang++ seems to assumewrapper<bar>::foo 总是阴影bar::foo ,即使 SFINAEd 出来了。这是错误消息:

main.cpp:30:26: error: no matching member function for call to 'foo'
assert(wrapper<bar>{}.foo(0));
~~~~~~~~~~~~~~~^~~

/usr/include/assert.h:92:5: note: expanded from macro 'assert'
((expr) \
^

/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.2.0/../../../../include/c++/5.2.0/type_traits:2388:44: note: candidate template ignored: disabled by 'enable_if' [with Arg = int]
using enable_if_t = typename enable_if<_Cond, _Tp>::type;
^

1 error generated.

那么,谁是对的?这段代码应该像 clang++ 一样被拒绝,还是应该工作并调用 bar::foo

最佳答案

考虑 §10.2:

In the declaration set, using-declarations are replaced by the set of designated members that are not hidden or overridden by members of the derived class (7.3.3),

然后 §7.3.3

When a using-declaration brings names from a base class into a derived class scope, […] member function templates in the derived class override and/or hide member functions and member function templates with the same name, parameter-type-list (8.3.5 [dcl.fct]), cv-qualification, and ref-qualifier (if any) in a base class (rather than conflicting).

显然,您的示例中的唯一区别在于返回类型。因此 Clang 是正确的,而 GCC 是有问题的。

措辞由CWG #1764引入:

According to 7.3.3 [namespace.udecl] paragraph 15,

When a using-declaration brings names from a base class into a derived class scope, […]

10.2中给出的类作用域名称查找算法 然而,[class.member.lookup] 并没有实现这个要求; 没有什么可以删除隐藏的基类成员(替换 using-declaration,根据第 3 段)来自结果集。

决议于 2014 年 2 月移至 DR,因此可能 GCC 尚未实现。


正如@TartanLlama 的回答中提到的,您可以介绍一个对应方来处理其他情况。类似的东西

template <typename Arg, typename=std::enable_if_t<std::is_constructible<Arg>{}>>
decltype(auto) foo(Arg a) const
{
return T::foo(a);
}

Demo .

关于c++ - SFINAEd-out 函数是否隐藏了从基类显式导入的重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33694192/

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