【发布时间】:2019-08-02 08:29:09
【问题描述】:
我的这段代码可以在 GCC 9.1 中正常工作:
#include <type_traits>
template< typename T >
class A
{
protected:
T value;
public:
template< typename U,
typename...,
typename = std::enable_if_t< std::is_fundamental< U >::value > >
A& operator=(U v)
{
value = v;
return *this;
}
};
template< typename T >
class B : public A<T>
{
public:
using A<T>::operator=;
template< typename U,
typename...,
typename = std::enable_if_t< ! std::is_fundamental< U >::value > >
B& operator=(U v)
{
this->value = v;
return *this;
}
};
int main()
{
B<int> obj;
obj = 2;
}
(实际上,我们会在B::operator= 中做一些花哨的事情,甚至对enable_if 使用不同的类型特征,但这是最简单的可重现示例。)
问题是 Clang 8.0.1 给出了一个错误,不知何故,来自父类的 operator= 不被考虑,虽然孩子有 using A<T>::operator=;:
test.cpp:39:9: error: no viable overloaded '='
obj = 2;
~~~ ^ ~
test.cpp:4:7: note: candidate function (the implicit copy assignment operator) not viable:
no known conversion from 'int' to 'const A<int>' for 1st argument
class A
^
test.cpp:4:7: note: candidate function (the implicit move assignment operator) not viable:
no known conversion from 'int' to 'A<int>' for 1st argument
class A
^
test.cpp:20:7: note: candidate function (the implicit copy assignment operator) not
viable: no known conversion from 'int' to 'const B<int>' for 1st argument
class B : public A<T>
^
test.cpp:20:7: note: candidate function (the implicit move assignment operator) not
viable: no known conversion from 'int' to 'B<int>' for 1st argument
class B : public A<T>
^
test.cpp:28:8: note: candidate template ignored: requirement
'!std::is_fundamental<int>::value' was not satisfied [with U = int, $1 = <>]
B& operator=(U v)
^
1 error generated.
根据标准,哪个编译器是正确的? (我正在使用-std=c++14 进行编译。)我应该如何更改代码以使其正确?
【问题讨论】:
-
请注意,clang 不是唯一拒绝您的代码的人:godbolt.org/z/bLp_i3
-
这很有趣,但它们是对还是错?
-
我猜他们是对的。你可以写这个wandbox.org/permlink/PPXl1iWpxO0icf3S
-
对于您之前的评论,请注意,icc 的问题可以通过添加另一个模板参数以使“签名”不同:godbolt.org/z/REouFh 它仍然不适用于 clang 或 msvc。
-
使用
std::enable_if_t<cond<T>::value, int> = 0>(相对于typename = std::enable_if_t<cond<T>::value>)也可以避免劫持(并且还允许重载)
标签: c++ c++14 language-lawyer overload-resolution name-hiding