You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 08:45:21