I'm designing a simple parser, which matches patterns. The code use some CRTP C design pattern, I have simplified the code as below.
#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;
}
You can see that when parsing the std::string_view
, it builds correctly.
Now, I would like to extent the std::string_view
, which is actually std::basic_string_view<char>
to other types, such as I would like to use my own Tokens, so I try to change the code like below:
#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;
}
With the above code, I simply add a second template parameter T
(which stands for Token) to the parser_base
class, and the following derived class and functions.
But I got the build error:
[ 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_'
It looks like the struct char_
should not be a class template? But how can I pass the T
type to the char_
class?
So, any ideas on how to solve my issue? Thanks.
CodePudding user response:
char_
is not a type it's a template, the type is char_<T>
. So
template<typename T>
struct char_ final : public parser_base<char_<T>, T> {