c++ - clang和gcc之间的右值引用重载区别
问题描述
我正在实现一个 map 函数,有两个重载:一个用于右值,另一个用于 const 引用:
template <class Array, class UnaryOp>
void map_inplace(UnaryOp op, Array &a) {
std::transform(a.cbegin(), a.cend(), a.begin(), op);
}
template <class Array, class UnaryOp>
auto map(UnaryOp op, Array &&a) {
map_inplace(op, a);
return a;
}
template <class Array, class UnaryOp>
auto map(UnaryOp op, const Array &a) {
Array res(a);
map_inplace(op, res);
return res;
}
我有以下测试:
TEST_CASE("map") {
const std::vector v{1., 2., 3.};
// I do expect the const reference overload to be called
REQUIRE(almost_equal(map(std::negate<>(), v), {-1., -2., -3.}));
// Check const vector is not modified
REQUIRE(v == std::vector{1., 2., 3.});
}
用 Clang 运行它测试通过:
通过:几乎等于(map(std::negate<>(), v), {-1., -2., -3.}) 为:true
通过: v == std::vector{1., 2., 3.} 对于: { 1.0, 2.0, 3.0 } == { 1.0, 2.0, 3.0 }
通过 1 个带有 2 个断言的测试用例。
但是 GCC 失败了:
通过:几乎等于(map(std::negate<>(), v), {-1., -2., -3.}) 为:true
失败:v == std::vector{1., 2., 3.} 对于:{ -1.0, -2.0, -3.0 } == { 1.0, 2.0, 3.0 }
1 个测试用例失败,1 个断言失败。
因此 GCC 正在调用右值引用重载并正在修改 const 定义的向量。
GCC 版本是:
gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
Clang 版本是:
clang 版本 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
编辑:
所以我尝试了更多测试,但 GCC 失败了:
TEST_CASE("map") {
const std::vector v{1., 2., 3.};
REQUIRE((map(std::negate<>(), v) == std::vector{-1., -2., -3.}));
REQUIRE(v == std::vector{1., 2., 3.});
}
但是如果我添加模板类型参数:
TEST_CASE("map") {
const std::vector<double> v{1., 2., 3.};
REQUIRE((map(std::negate<>(), v) == std::vector<double>{-1., -2., -3.}));
REQUIRE(v == std::vector<double>{1., 2., 3.});
}
那么它的工作原理!
解决方案
演示此问题的最小示例:
#include <vector>
#include <type_traits>
const ::std::vector<double> v1{1., 2., 3.};
const ::std::vector v{1., 2., 3.};
static_assert(::std::is_same_v<decltype(v1), decltype(v)>); // error on gcc
推荐阅读
- linux - EADDRNOTAVAIL 丢弃 IGMPv2 成员资格并在间隔内强制发送重新加入
- pine-script - 如何在显示网格中增加小数?
- charts - Crystal Reports - 我有一个在子报表上使用至少 1 个图表的报表 - 如有必要,可以使用 2 个。我需要根据产品修改条间距
- reactjs - 复选框检查未使用传入值
- css - 如何在 Reactjs 中使用字体 awesome all.min.css CSS 工具包
- excel - 使用最后一行代码循环整个列
- visual-studio-2019 - VS2019 的 Visual Studio 远程调试器工具的下载链接在哪里
- python - cv2.blur 中的深色边框
- flutter - Flutter 应用程序在应用程序之外时关闭
- netflix-eureka - 如何在不同数据中心的多个eureka集群之间切换