为何std::integral auto&&形参无法匹配左值实参
问题分析与修复方案
问题代码
#include <array> #include <algorithm> #include <type_traits> #include <concepts> #include <cstdio> #include <cwchar> template <typename T> concept Character = std::same_as< std::remove_cv_t<T>, char > || std::same_as< std::remove_cv_t<T>, signed char > || std::same_as< std::remove_cv_t<T>, unsigned char > || std::same_as< std::remove_cv_t<T>, wchar_t > || std::same_as< std::remove_cv_t<T>, char8_t > || std::same_as< std::remove_cv_t<T>, char16_t > || std::same_as< std::remove_cv_t<T>, char32_t >; template <std::size_t N> consteval auto create_character_array( std::integral auto&& fill_character ) noexcept { std::array<std::remove_cvref_t<decltype( fill_character )>, N> dashes { }; std::fill( std::begin( dashes ), std::end( dashes ), fill_character ); return dashes; } int main( ) { const char ch { '^' }; auto dashes { create_character_array<128>( ch ) }; dashes.back( ) = '\0'; std::fputs( std::data( dashes ), stdout ); }
问题原因
传入左值ch时,万能引用auto&&会将auto推导为const char&,但std::integral概念仅对非引用的整数类型生效(std::is_integral_v<const char&>为false),因此约束不满足导致编译失败。而传入字面量'^'时,auto推导为char(非引用类型),满足std::integral约束,所以可以正常编译。
修复方案
核心思路是让概念约束作用于移除引用和cv限定后的底层类型,而非引用类型本身。以下是几种可行的写法:
写法1:显式模板参数+移除引用后的约束
template <std::size_t N, typename T> requires std::integral<std::remove_reference_t<T>> consteval auto create_character_array(T&& fill_character) noexcept { using CharType = std::remove_cvref_t<T>; std::array<CharType, N> dashes{}; std::fill(std::begin(dashes), std::end(dashes), fill_character); return dashes; }
写法2:requires子句直接检查参数底层类型
template <std::size_t N> consteval auto create_character_array(auto&& fill_character) noexcept requires std::integral<std::remove_cvref_t<decltype(fill_character)>> { using CharType = std::remove_cvref_t<decltype(fill_character)>; std::array<CharType, N> dashes{}; std::fill(std::begin(dashes), std::end(dashes), fill_character); return dashes; }
写法3:适配自定义Character概念
如果要使用自定义的Character概念,只需修改requires子句即可:
template <std::size_t N> consteval auto create_character_array(auto&& fill_character) noexcept requires Character<std::remove_cvref_t<decltype(fill_character)>> { using CharType = std::remove_cvref_t<decltype(fill_character)>; std::array<CharType, N> dashes{}; std::fill(std::begin(dashes), std::end(dashes), fill_character); return dashes; }
以上三种写法都能兼容左值、右值等任意值类别,同时保证参数类型符合预期的整数/字符类型约束。
内容的提问来源于stack exchange,提问作者digito_evo
相关产品推荐
相关产品推荐

