C++20检测模板成员函数存在性时编译错误求助
问题分析与解决:C++20中模板成员函数存在性检测编译错误
问题根源
当注释掉TestClass的allocate模板成员函数后,编译器尝试匹配AllocatorTraits里的第二个allocate重载,但原代码中这个重载仅接受单个模板参数:
template <typename> static std::false_type allocate(...);
而我们调用时传入的是多个模板参数(Allocator, T, Args...),模板参数数量不匹配,直接触发编译错误C2672: 找不到匹配的重载函数。反观malloc的检测逻辑,调用时只传了Allocator一个模板参数,所以第二个重载能正常匹配,不会报错。
修复方案
把第二个allocate重载的模板参数改为可变参数模板,让它能接受任意数量的模板参数,这样在第一个重载因SFINAE(替换失败并非错误)被排除时,第二个重载能成功匹配并返回std::false_type。
修改后的完整代码:
#include <type_traits> template <typename Allocator> struct AllocatorTraits { private: template <typename U> static auto malloc(int) -> decltype(static_cast<void* (U::*)(size_t)>(&U::malloc), std::true_type()); template <typename> static std::false_type malloc(...); template <typename U, typename T, typename... Args> static auto allocate(int) -> decltype(static_cast<T* (U::*)(Args...)>(&U::template allocate<T, Args...>), std::true_type()); // 核心修改:改为可变参数模板,适配任意数量的模板参数传入 template <typename...> static std::false_type allocate(...); public: static constexpr bool has_malloc = decltype(malloc<Allocator>(0))::value; template <typename T, typename... Args> static constexpr bool has_allocate = decltype(allocate<Allocator, T, Args...>(0))::value; }; class TestClass { public: void* malloc(size_t size) noexcept { return nullptr; } // 注释此行可测试错误修复效果 template <typename T, typename ...Args> T* allocate(Args &&...args) noexcept { return nullptr; } }; static constexpr bool test_malloc = AllocatorTraits<TestClass>::has_malloc; static constexpr bool test_allocate = AllocatorTraits<TestClass>::has_allocate<int>;
修复逻辑说明
- 当
Allocator存在符合签名的allocate模板成员函数时,第一个重载会被优先选中,返回std::true_type; - 当
Allocator没有该函数时,第一个重载因SFINAE被排除,第二个可变参数模板重载会匹配任意数量的传入模板参数,返回std::false_type,编译流程正常执行。
验证效果
- 保留
TestClass::allocate时,test_allocate的值为true; - 注释
TestClass::allocate后,test_allocate的值为false,编译无报错。
内容的提问来源于stack exchange,提问作者Craig Stoneham
相关产品推荐
相关产品推荐

