跳到主要内容
左猫娘右猫娘

MSVC的requires缺陷

· 阅读需 4 分钟
Heng_Xin
ここから先は一方通行だ!

MSVC你真的牛逼大了!, 这种简单活都干不好? win都💩你无敌了 (\💩/ \💩/ \💩/)

Tip

本文只有恶意. win都💩! MS💩VC!

\💩/ \💩/ \💩/ \💩/ \💩/

msvc签名不完全匹配: requires 缺陷

今天上win, 顺便把之前的msvc bug 修复. 结果发现: (#13)

D:\command\Github\HXLibs\tests\client\02_ws_client.cpp
[build] D:\command\Github\HXLibs\include\HXLibs/container/ThreadPool.hpp(338): error C2244: “HX::container::FutureResult<T>::thenTry”: 无法将函数定义与现有的声明匹配
[build] D:\command\Github\HXLibs\include\HXLibs/container/ThreadPool.hpp(338): note: 参见“HX::container::FutureResult<T>::thenTry”的声明
[build] D:\command\Github\HXLibs\include\HXLibs/container/ThreadPool.hpp(338): note: 定义
[build] D:\command\Github\HXLibs\include\HXLibs/container/ThreadPool.hpp(338): note: 'HX::container::FutureResult<internal::RemoveTryWarpImpl<Res>::Type> HX::container::FutureResult<T>::thenTry(Func &&) noexcept &&'
[build] D:\command\Github\HXLibs\include\HXLibs/container/ThreadPool.hpp(338): note: 现有声明
[build] D:\command\Github\HXLibs\include\HXLibs/container/FutureResult.hpp(127): note: 'HX::container::FutureResult<internal::RemoveTryWarpImpl<Res>::Type> HX::container::FutureResult<T>::thenTry(Func &&) noexcept &&'
[build] ninja: build stopped: subcommand failed.
cpp

经过排查, 发现是 msvc 的缺陷. 要求 requires 在函数签名中应该完全一样, 才会视作函数签名一样.

以下是复现案例: https://godbolt.org/z/EWhrdsoK6

#include <utility>
#include <type_traits>

template <typename T = void>
struct Try {
using TryType = T;
};

namespace internal {

template <typename T>
struct RemoveTryWarpImpl {
using Type = T;
};

template <typename T>
struct RemoveTryWarpImpl<Try<T>> {
using Type = T;
};

} // namespace internal

template <typename T>
using RemoveTryWarpType = internal::RemoveTryWarpImpl<T>::Type;

template <typename T = void>
class FutureResult {
public:
using TryType = Try<RemoveTryWarpType<T>>;

template <typename Func, typename Res = std::invoke_result_t<Func, TryType>>
requires (requires (Func func, TryType t) { // 应该写为 FutureResult<T>::TryType
func(std::move(t)); // MSVC的错误是签名不完全匹配,
// 原因是requires表达式写在了类模板声明和定义上,
// 但是MSVC对这类情况的解析有bug,
// 具体是 [requires必须一模一样, 否则视为不同函数]。
// requires表达式里类型写法不一致, 导致MSVC无法匹配。
})
FutureResult<RemoveTryWarpType<Res>> thenTry(Func&& func) && noexcept;
};

template <typename T>
template <typename Func, typename Res>
requires (requires (Func func, FutureResult<T>::TryType t) {
func(std::move(t));
})
FutureResult<RemoveTryWarpType<Res>> FutureResult<T>::thenTry(
Func&& func
) && noexcept { return {}; }

int main() {
FutureResult<int> f;
auto res = std::move(f).thenTry([](Try<int> x) {
return x;
});
}
cpp

更加简单的, 最小复现案例: https://godbolt.org/z/xG1cjjbca

#include <utility>
#include <type_traits>

template <typename T = void>
struct Try { using TryType = T; };

template <typename T = void>
class FutureResult {
public:
using TryType = Try<T>;

template <typename Func>
requires requires(Func func, TryType t) { func(std::move(t)); }
FutureResult thenTry(Func&& func) && noexcept;
};

template <typename T>
template <typename Func>
requires requires(Func func, typename FutureResult<T>::TryType t) { func(std::move(t)); }
FutureResult<T> FutureResult<T>::thenTry(Func&& func) && noexcept {
return {};
}

int main() {
FutureResult<int> f;
std::move(f).thenTry([](Try<int> x) { return x; });
}
cpp

已经发送给 msvc 了 (https://developercommunity.visualstudio.com/t/MSVC-rejects-definitions-when-requires-c/10961820) (我才不管是否有重复提案呢..tm的这么久了都还有这个bug...)

之前我提的 ice 都不鸟我. 美名其曰 我们的团队优先考虑对具有广泛客户影响的产品问题采取行动。. 还是机器人回复. 你们开源节流还有真人吗? 人机!

呵呵, MSVC 和 win都💩

请作者喝奶茶:
Alipay IconQR Code
Alipay IconQR Code
本文遵循 CC CC 4.0 BY-SA 版权协议, 转载请标明出处
Loading Comments...