C++:MSC 不解析模板运算符(gcc 和 clang ok)
C++: MSC not resolving a template operator (gcc and clang ok)
我有一个关于 C++ 运算符在模板 class 和类型上重载的问题,虽然它被 gcc 和 clang(Linux 和 macOS)接受,但 Microsoft Visual C++ 没有正确解析它。
我怀疑这是 MSVC++ 中的一个错误,但我想在报告错误之前征求专家的意见,以防它可能是相反的(gcc 和 clang 是错误的)。
这个想法是一个模板 class,它必须用某种整数类型实例化。我们想用任何其他普通整数类型定义加法,两种方式 (class + int 和 int + class).
我可以重现问题的最少代码如下:
#include <type_traits>
template <typename INT, typename std::enable_if<std::is_integral<INT>::value>::type* = nullptr>
class A
{
public:
template<typename INT2>
A operator+(INT2 x) const { return A(); }
};
template <typename INT1, typename INT2>
A<INT2> operator+(INT1 x1, A<INT2> x2) { return x2 + x1; }
int main(int argc, char* argv[])
{
typedef A<int> B;
B x, y;
y = x + 1; // ok everywhere
y = 1 + x; // VC++: error C2677: binary '+': no global operator found which takes type 'B' (or there is no acceptable conversion)
}
在原始代码中,到处都有 SFINAE 构造以在必要时强制执行类型检查(包括在两个“+”运算符中)。当他们没有更改编译错误时,我已将它们全部删除。只有 class A 定义中的“enable_if”是必需的。没有它,代码可以用 MSVC++ 编译。
微软 Visual Studio 2019,版本 16.9.3。
这里有什么问题? MSVC++ 或 gcc/clang?
感谢您的建议。
如果我们学究气,在 C++17 中,非类型模板参数不能具有类型 void*
,参见 [temp.param]/4.2:
A non-type template-parameter shall have one of the following (optionally cv-qualified) types:
. . .
— pointer to object or pointer to function,
. . .
(注意:在C++20中已经是rectified)。
所以 MSVC 中似乎出了点问题(SFINAE 本身在 A
中成功,但导致运算符查找失败)。 MSVC 尚不完全支持 C++20,但仍值得报告此问题。
为了更便携的代码,使用基于int
而不是void*
的SFINAE:
template <typename INT, typename std::enable_if<std::is_integral<INT>::value, int>::type = 0>
class A {
. . .
这在 MSVC 16.9 中编译正常。
我有一个关于 C++ 运算符在模板 class 和类型上重载的问题,虽然它被 gcc 和 clang(Linux 和 macOS)接受,但 Microsoft Visual C++ 没有正确解析它。
我怀疑这是 MSVC++ 中的一个错误,但我想在报告错误之前征求专家的意见,以防它可能是相反的(gcc 和 clang 是错误的)。
这个想法是一个模板 class,它必须用某种整数类型实例化。我们想用任何其他普通整数类型定义加法,两种方式 (class + int 和 int + class).
我可以重现问题的最少代码如下:
#include <type_traits>
template <typename INT, typename std::enable_if<std::is_integral<INT>::value>::type* = nullptr>
class A
{
public:
template<typename INT2>
A operator+(INT2 x) const { return A(); }
};
template <typename INT1, typename INT2>
A<INT2> operator+(INT1 x1, A<INT2> x2) { return x2 + x1; }
int main(int argc, char* argv[])
{
typedef A<int> B;
B x, y;
y = x + 1; // ok everywhere
y = 1 + x; // VC++: error C2677: binary '+': no global operator found which takes type 'B' (or there is no acceptable conversion)
}
在原始代码中,到处都有 SFINAE 构造以在必要时强制执行类型检查(包括在两个“+”运算符中)。当他们没有更改编译错误时,我已将它们全部删除。只有 class A 定义中的“enable_if”是必需的。没有它,代码可以用 MSVC++ 编译。
微软 Visual Studio 2019,版本 16.9.3。
这里有什么问题? MSVC++ 或 gcc/clang?
感谢您的建议。
如果我们学究气,在 C++17 中,非类型模板参数不能具有类型 void*
,参见 [temp.param]/4.2:
A non-type template-parameter shall have one of the following (optionally cv-qualified) types:
. . .
— pointer to object or pointer to function,
. . .
(注意:在C++20中已经是rectified)。
所以 MSVC 中似乎出了点问题(SFINAE 本身在 A
中成功,但导致运算符查找失败)。 MSVC 尚不完全支持 C++20,但仍值得报告此问题。
为了更便携的代码,使用基于int
而不是void*
的SFINAE:
template <typename INT, typename std::enable_if<std::is_integral<INT>::value, int>::type = 0>
class A {
. . .
这在 MSVC 16.9 中编译正常。