C++ CRTP模式下扩展std::basic_string_view<T>的编译错误求助
解决CRTP模板类扩展支持
std::basic_string_view<T>的编译错误 问题描述
我正在设计一个基于CRTP设计模式的简单模式匹配解析器,针对std::string_view的版本可正常编译:
#include <string_view> template <typename Base> struct parser_base { constexpr auto operator[](std::string_view& output) const noexcept; }; struct char_ final : public parser_base<char_> { constexpr explicit char_(const char ch) noexcept : ch(ch) {} constexpr inline bool visit(std::string_view& sv) const& noexcept { if (!sv.empty() && sv.front() == ch) { sv.remove_prefix(1); return true; } return false; } private: char ch; }; template <typename Parser> constexpr bool parse(std::string_view input, Parser const& parser) noexcept { return parser.visit(input); } int main() { return 0; }
现希望将其扩展为支持std::basic_string_view<T>(std::string_view本质是std::basic_string_view<char>),以使用自定义Token类型,修改后的代码如下:
#include <string_view> template <typename Base, typename T> struct parser_base { constexpr auto operator[](std::basic_string_view<T>& output) const noexcept; }; template<typename T> struct char_ final : public parser_base<char_, T> { constexpr explicit char_(const T ch) noexcept : ch(ch) {} constexpr inline bool visit(std::basic_string_view<T>& sv) const& noexcept { if (!sv.empty() && sv.front() == ch) { sv.remove_prefix(1); return true; } return false; } private: T ch; }; template <typename Parser, typename T> constexpr bool parse(std::basic_string_view<T> input, Parser const& parser) noexcept { return parser.visit(input); } int main() { return 0; }
编译时出现如下错误:
[ 50.0%] g++.exe -Wall -fexceptions -g -c F:\code\test_crtp_twoargs\main.cpp -o obj\Debug\main.o F:\code\test_crtp_twoargs\main.cpp:46:49: error: type/value mismatch at argument 1 in template parameter list for 'template<class Base, class T> struct parser_base' 46 | struct char_ final : public parser_base<char_, T> { | ^ F:\code\test_crtp_twoargs\main.cpp:46:49: note: expected a type, got 'char_'
需要将T类型传入char_类,同时解决这个编译错误。
解决方案
编译错误的核心原因是:parser_base的第一个模板参数要求是具体类型,但char_是未实例化的模板类,不是合法类型。需要将char_的完整实例化类型char_<T>传递给parser_base,修改后的代码如下:
#include <string_view> template <typename Base, typename T> struct parser_base { constexpr auto operator[](std::basic_string_view<T>& output) const noexcept; }; template<typename T> struct char_ final : public parser_base<char_<T>, T> { // 将char_改为char_<T> constexpr explicit char_(const T ch) noexcept : ch(ch) {} constexpr inline bool visit(std::basic_string_view<T>& sv) const& noexcept { if (!sv.empty() && sv.front() == ch) { sv.remove_prefix(1); return true; } return false; } private: T ch; }; template <typename Parser, typename T> constexpr bool parse(std::basic_string_view<T> input, Parser const& parser) noexcept { return parser.visit(input); } int main() { return 0; }
关键说明
- 在CRTP模式中,基类需要的是派生类的具体实例类型。当派生类本身是模板类时,必须传递其完整的实例化形式(如
char_<T>),而非模板名char_。 - 修改后,
parser_base的第一个模板参数变为合法的具体类型,编译错误即可消除。
内容的提问来源于stack exchange,提问作者ollydbg
相关产品推荐
相关产品推荐

