C++ CRTP:如何通过传递模板参数将std::string_view扩展为std::basic_string_view< T>

hjzp0vay  于 2023-02-06  发布在  其他
关注(0)|答案(1)|浏览(123)

我正在设计一个简单的模式匹配解析器。代码使用了一些CRTP C++设计模式,我将代码简化如下。

#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::string_view时,它构建正确。
现在,我想扩展std::string_view,它实际上是std::basic_string_view<char>到其他类型,例如我想使用我自己的令牌,所以我尝试更改代码如下:

#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;
}

使用上面的代码,我只需要向parser_base类添加第二个模板参数T(代表Token),以及以下派生类和函数。
但我得到了构建错误:

[ 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_'

看起来struct char_不应该是一个类模板,但是我怎么把T类型传递给char_类呢?
有什么办法能解决我的问题吗?谢谢。

wn9m85ua

wn9m85ua1#

它不是一个类型,它是一个模板,类型是

template<typename T>
struct char_ final : public parser_base<char_<T>, T> {

相关问题