MSVC 无法编译 SFINAE 检查
MSVC fails to compile SFINAE checks
我应该注意一些编译器标志吗?以下代码工作正常,并且符合GCC和Clang的预期,但不是MSVC。是什么让std::allocator
的分配在这里如此不同?
#include <type_traits>
#include <memory>
template <typename T, typename = std::void_t<>>
constexpr bool declares_allocate = false;
template <typename T>
constexpr bool declares_allocate<T, std::void_t<decltype(&T::allocate)>> = true;
struct normal_struct {
auto allocate() -> void {}
};
template <typename T>
struct struct_template {
auto allocate() -> void {}
};
template <typename T>
class class_template_public {
public:
auto allocate() -> void {}
};
template <typename T>
class class_template_private {
private:
auto allocate() -> void {}
};
auto main() -> int {
auto allocator = std::allocator<float>();
auto memory = allocator.allocate(1024);
static_assert(declares_allocate<normal_struct>); // pass
static_assert(declares_allocate<struct_template<float>>); // pass
static_assert(declares_allocate<class_template_public<float>>); // pass
// static_assert(declares_allocate<class_template_private<float>>); // fails
static_assert(declares_allocate<std::allocator<float>>); // fails when compiled by MSVC but not Clang or GCC
allocator.deallocate(memory, 1024);
return 0;
}
https://godbolt.org/z/GVyNQZ
根据C++标准实现,std::allocator<T>::allocate
可以定义为:
T* allocate(size_t n, const void* hint = 0);
T* allocate(size_t n);
T* allocate(size_t n, const void* hint); // deprecating usage of hint
T* allocate(size_t n);
也就是说,第二个实现将allocate
转换为重载成员函数。这个目前在MSVC的标准库中使用:
_NODISCARD __declspec(allocator) _Ty* allocate(_CRT_GUARDOVERFLOW const size_t _Count) {
return static_cast<_Ty*>(_Allocate<_New_alignof<_Ty>>(_Get_size_of_n<sizeof(_Ty)>(_Count)));
}
_CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS _NODISCARD __declspec(allocator) _Ty* allocate(
_CRT_GUARDOVERFLOW const size_t _Count, const void*) {
return allocate(_Count);
}
这种实现使&T::allocate
模棱两可,因此在替换过程中被拒绝。
相关文章:
- MSVC 无法编译 SFINAE 检查
- SFINAE 检查模板参数运算符
- 尝试编译SFINAE检查中使用的方法体时发生编译错误
- 检查类型 T 是否具有成员函数 SFINAE 的任何重载
- 使用 SFINAE 检查函数 std::to_string 是否存在类型
- SFINAE 优雅地检查"template template class"(在模板参数中)
- SFINAE 检查 std::less 是否有效
- 在VS2015上使用SFINAE的模板上检查方法存在
- 使用 SFINAE 检查模板参数继承
- 如何使用sfinae检查,类型是否有运算符()?
- C++SFINAE运算符/函数结果类型检查
- SFINAE 使用 decltype 检查静态成员
- 使用SFINAE检查类型是否可以绑定到模板模板参数
- C ++ SFINAE 检查指向类的指针中的方法
- 我的SFINAE检查std::map/std::vector有什么问题
- SFINAE检查运算符+=
- 使用SFINAE检查该类是否相同或是从C++98中的另一个模板类派生的
- 应用SFINAE检查是否为T定义了一个trait
- SFINAE检查操作员[]比我更困惑
- 使用 SFINAE 检查全局运算符<<?