C++17 constexpr string parsing
Clash Royale CLAN TAG#URR8PPP
up vote
15
down vote
favorite
Sorry that this will be a long post, but I feel like you need all of the code to see what's going on.
So, I have been experimenting with an idea for compile time string to data structure parser. Think of something like a regex, where the string is "compiled" into a data structure at compile time but executed at runtime (so long as the input string is a constant of course). But I've run into an issue that I don't quite understand what's wrong:
Basically, my design is a 2 pass parser:
- Pass 1: determine how many "opcodes" are in the input string
- Pass 2: return an array whose size is determined by Pass 1, and filled in with the "opcodes"
Here's what things look like:
// a class to wrap string constants
class constexpr_string
public:
template <size_t N>
constexpr constexpr_string(const char (&s)[N]) : string_(s), size_(N - 1)
public:
constexpr size_t size() const return size_;
constexpr size_t capacity() const return size();
constexpr size_t empty() const return size() != 0;
public:
constexpr char operator(size_t n) const return string_[n];
private:
const char *string_;
size_t size_;
;
// would have loved to use std::array, but ran into an issue so..
// wrapped in a struct so we can return it
template <class T, size_t N>
struct constexpr_array
T array[N] = ;
;
struct opcode /* not relevant */ ;
template <size_t N>
constexpr constexpr_array<opcode, N> compile_string(constexpr_string fmt)
constexpr_array<opcode, N> compiled;
/* fill in compiled_format */
return compiled;
constexpr size_t calculate_size(constexpr_string fmt)
size_t size = 0;
/* calculate size */
return size;
#if 0
// NOTE: Why doesn't **This** work?
constexpr int test(constexpr_string input)
constexpr size_t compiled_size = calculate_size(input);
constexpr auto compiled_format = compile_string<compiled_size>(input);
return 0;
#endif
int main()
// NOTE: when this works...
constexpr char input = "...";
constexpr size_t compiled_size = calculate_size(input);
constexpr auto compiled = compile_string<compiled_size>(input);
execute(compiled); // run it!
So far so good!
The problem arises when I try to just wrap those 2 lines into a function :-/.
I don't understand why the same exact code works in main
, but if I just try to pass the sameconstexpr
object to another function, I start getting errors about things not being constexpr
.
Here's the error message:
main.cpp: In function âÂÂconstexpr int test(constexpr_string)âÂÂ:
main.cpp:258:55: error: âÂÂinputâ is not a constant expression
constexpr size_t compiled_size = calculate_size(input);
^
main.cpp:259:70: error: no matching function for call to âÂÂcompile_string<compiled_size>(constexpr_string&)âÂÂ
constexpr auto compiled_format = compile_string<compiled_size>(input);
^
main.cpp:60:45: note: candidate: template<long unsigned int N> constexpr constexpr_array<opcode, N> compile_string(constexpr_string)
constexpr constexpr_array<opcode, N> compile_string(constexpr_string fmt) {
^~~~~~~~~~~~~~
main.cpp:60:45: note: template argument deduction/substitution failed:
c++ parsing c++17 constexpr
 |Â
show 1 more comment
up vote
15
down vote
favorite
Sorry that this will be a long post, but I feel like you need all of the code to see what's going on.
So, I have been experimenting with an idea for compile time string to data structure parser. Think of something like a regex, where the string is "compiled" into a data structure at compile time but executed at runtime (so long as the input string is a constant of course). But I've run into an issue that I don't quite understand what's wrong:
Basically, my design is a 2 pass parser:
- Pass 1: determine how many "opcodes" are in the input string
- Pass 2: return an array whose size is determined by Pass 1, and filled in with the "opcodes"
Here's what things look like:
// a class to wrap string constants
class constexpr_string
public:
template <size_t N>
constexpr constexpr_string(const char (&s)[N]) : string_(s), size_(N - 1)
public:
constexpr size_t size() const return size_;
constexpr size_t capacity() const return size();
constexpr size_t empty() const return size() != 0;
public:
constexpr char operator(size_t n) const return string_[n];
private:
const char *string_;
size_t size_;
;
// would have loved to use std::array, but ran into an issue so..
// wrapped in a struct so we can return it
template <class T, size_t N>
struct constexpr_array
T array[N] = ;
;
struct opcode /* not relevant */ ;
template <size_t N>
constexpr constexpr_array<opcode, N> compile_string(constexpr_string fmt)
constexpr_array<opcode, N> compiled;
/* fill in compiled_format */
return compiled;
constexpr size_t calculate_size(constexpr_string fmt)
size_t size = 0;
/* calculate size */
return size;
#if 0
// NOTE: Why doesn't **This** work?
constexpr int test(constexpr_string input)
constexpr size_t compiled_size = calculate_size(input);
constexpr auto compiled_format = compile_string<compiled_size>(input);
return 0;
#endif
int main()
// NOTE: when this works...
constexpr char input = "...";
constexpr size_t compiled_size = calculate_size(input);
constexpr auto compiled = compile_string<compiled_size>(input);
execute(compiled); // run it!
So far so good!
The problem arises when I try to just wrap those 2 lines into a function :-/.
I don't understand why the same exact code works in main
, but if I just try to pass the sameconstexpr
object to another function, I start getting errors about things not being constexpr
.
Here's the error message:
main.cpp: In function âÂÂconstexpr int test(constexpr_string)âÂÂ:
main.cpp:258:55: error: âÂÂinputâ is not a constant expression
constexpr size_t compiled_size = calculate_size(input);
^
main.cpp:259:70: error: no matching function for call to âÂÂcompile_string<compiled_size>(constexpr_string&)âÂÂ
constexpr auto compiled_format = compile_string<compiled_size>(input);
^
main.cpp:60:45: note: candidate: template<long unsigned int N> constexpr constexpr_array<opcode, N> compile_string(constexpr_string)
constexpr constexpr_array<opcode, N> compile_string(constexpr_string fmt) {
^~~~~~~~~~~~~~
main.cpp:60:45: note: template argument deduction/substitution failed:
c++ parsing c++17 constexpr
Since this question is tagged with c++17, have you ever considered usingstd::string_view
in your implementation?std::string_view
is build withconstexpr
in mind, so it is definitely worth looking. en.cppreference.com/w/cpp/header/string_view
â HugoTeixeira
Aug 8 at 2:03
@HugoTeixeira Definitely. My plan is/was to switch to a string_view once I had the core concepts of what I was experimenting with working how I want.
â Evan Teran
Aug 8 at 2:05
Is there any reason you have to use a string? Representing regex rules (e.g. the kleene star) using operators or objects would probably be significantly easier. I believe that's what Boost.Spirit does.
â Pharap
Aug 8 at 2:05
well, "regex" is was intended as an analogy for what I want to do. As in: string -> state -> execute_state. I was hoping for a nice way to do the first part at compile time... It looks like it will be a bit complicated to do so though.
â Evan Teran
Aug 8 at 2:07
You may be interested in the experimentalconstexpr
JSON parser by Ben Deane and Jason Turner. Their experiments are titled constexpr all the things. There have been talks at C++Now 2017 (youtu.be/HMB9oXFobJc) and CppCon 2017 (youtu.be/PJwd4JLYJJY). The source code is on GitHub, but I recommend watching the talk.
â Julius
Aug 8 at 6:14
 |Â
show 1 more comment
up vote
15
down vote
favorite
up vote
15
down vote
favorite
Sorry that this will be a long post, but I feel like you need all of the code to see what's going on.
So, I have been experimenting with an idea for compile time string to data structure parser. Think of something like a regex, where the string is "compiled" into a data structure at compile time but executed at runtime (so long as the input string is a constant of course). But I've run into an issue that I don't quite understand what's wrong:
Basically, my design is a 2 pass parser:
- Pass 1: determine how many "opcodes" are in the input string
- Pass 2: return an array whose size is determined by Pass 1, and filled in with the "opcodes"
Here's what things look like:
// a class to wrap string constants
class constexpr_string
public:
template <size_t N>
constexpr constexpr_string(const char (&s)[N]) : string_(s), size_(N - 1)
public:
constexpr size_t size() const return size_;
constexpr size_t capacity() const return size();
constexpr size_t empty() const return size() != 0;
public:
constexpr char operator(size_t n) const return string_[n];
private:
const char *string_;
size_t size_;
;
// would have loved to use std::array, but ran into an issue so..
// wrapped in a struct so we can return it
template <class T, size_t N>
struct constexpr_array
T array[N] = ;
;
struct opcode /* not relevant */ ;
template <size_t N>
constexpr constexpr_array<opcode, N> compile_string(constexpr_string fmt)
constexpr_array<opcode, N> compiled;
/* fill in compiled_format */
return compiled;
constexpr size_t calculate_size(constexpr_string fmt)
size_t size = 0;
/* calculate size */
return size;
#if 0
// NOTE: Why doesn't **This** work?
constexpr int test(constexpr_string input)
constexpr size_t compiled_size = calculate_size(input);
constexpr auto compiled_format = compile_string<compiled_size>(input);
return 0;
#endif
int main()
// NOTE: when this works...
constexpr char input = "...";
constexpr size_t compiled_size = calculate_size(input);
constexpr auto compiled = compile_string<compiled_size>(input);
execute(compiled); // run it!
So far so good!
The problem arises when I try to just wrap those 2 lines into a function :-/.
I don't understand why the same exact code works in main
, but if I just try to pass the sameconstexpr
object to another function, I start getting errors about things not being constexpr
.
Here's the error message:
main.cpp: In function âÂÂconstexpr int test(constexpr_string)âÂÂ:
main.cpp:258:55: error: âÂÂinputâ is not a constant expression
constexpr size_t compiled_size = calculate_size(input);
^
main.cpp:259:70: error: no matching function for call to âÂÂcompile_string<compiled_size>(constexpr_string&)âÂÂ
constexpr auto compiled_format = compile_string<compiled_size>(input);
^
main.cpp:60:45: note: candidate: template<long unsigned int N> constexpr constexpr_array<opcode, N> compile_string(constexpr_string)
constexpr constexpr_array<opcode, N> compile_string(constexpr_string fmt) {
^~~~~~~~~~~~~~
main.cpp:60:45: note: template argument deduction/substitution failed:
c++ parsing c++17 constexpr
Sorry that this will be a long post, but I feel like you need all of the code to see what's going on.
So, I have been experimenting with an idea for compile time string to data structure parser. Think of something like a regex, where the string is "compiled" into a data structure at compile time but executed at runtime (so long as the input string is a constant of course). But I've run into an issue that I don't quite understand what's wrong:
Basically, my design is a 2 pass parser:
- Pass 1: determine how many "opcodes" are in the input string
- Pass 2: return an array whose size is determined by Pass 1, and filled in with the "opcodes"
Here's what things look like:
// a class to wrap string constants
class constexpr_string
public:
template <size_t N>
constexpr constexpr_string(const char (&s)[N]) : string_(s), size_(N - 1)
public:
constexpr size_t size() const return size_;
constexpr size_t capacity() const return size();
constexpr size_t empty() const return size() != 0;
public:
constexpr char operator(size_t n) const return string_[n];
private:
const char *string_;
size_t size_;
;
// would have loved to use std::array, but ran into an issue so..
// wrapped in a struct so we can return it
template <class T, size_t N>
struct constexpr_array
T array[N] = ;
;
struct opcode /* not relevant */ ;
template <size_t N>
constexpr constexpr_array<opcode, N> compile_string(constexpr_string fmt)
constexpr_array<opcode, N> compiled;
/* fill in compiled_format */
return compiled;
constexpr size_t calculate_size(constexpr_string fmt)
size_t size = 0;
/* calculate size */
return size;
#if 0
// NOTE: Why doesn't **This** work?
constexpr int test(constexpr_string input)
constexpr size_t compiled_size = calculate_size(input);
constexpr auto compiled_format = compile_string<compiled_size>(input);
return 0;
#endif
int main()
// NOTE: when this works...
constexpr char input = "...";
constexpr size_t compiled_size = calculate_size(input);
constexpr auto compiled = compile_string<compiled_size>(input);
execute(compiled); // run it!
So far so good!
The problem arises when I try to just wrap those 2 lines into a function :-/.
I don't understand why the same exact code works in main
, but if I just try to pass the sameconstexpr
object to another function, I start getting errors about things not being constexpr
.
Here's the error message:
main.cpp: In function âÂÂconstexpr int test(constexpr_string)âÂÂ:
main.cpp:258:55: error: âÂÂinputâ is not a constant expression
constexpr size_t compiled_size = calculate_size(input);
^
main.cpp:259:70: error: no matching function for call to âÂÂcompile_string<compiled_size>(constexpr_string&)âÂÂ
constexpr auto compiled_format = compile_string<compiled_size>(input);
^
main.cpp:60:45: note: candidate: template<long unsigned int N> constexpr constexpr_array<opcode, N> compile_string(constexpr_string)
constexpr constexpr_array<opcode, N> compile_string(constexpr_string fmt) {
^~~~~~~~~~~~~~
main.cpp:60:45: note: template argument deduction/substitution failed:
c++ parsing c++17 constexpr
edited Aug 8 at 5:54
Tas
5,10732342
5,10732342
asked Aug 7 at 23:18
Evan Teran
64.7k18153216
64.7k18153216
Since this question is tagged with c++17, have you ever considered usingstd::string_view
in your implementation?std::string_view
is build withconstexpr
in mind, so it is definitely worth looking. en.cppreference.com/w/cpp/header/string_view
â HugoTeixeira
Aug 8 at 2:03
@HugoTeixeira Definitely. My plan is/was to switch to a string_view once I had the core concepts of what I was experimenting with working how I want.
â Evan Teran
Aug 8 at 2:05
Is there any reason you have to use a string? Representing regex rules (e.g. the kleene star) using operators or objects would probably be significantly easier. I believe that's what Boost.Spirit does.
â Pharap
Aug 8 at 2:05
well, "regex" is was intended as an analogy for what I want to do. As in: string -> state -> execute_state. I was hoping for a nice way to do the first part at compile time... It looks like it will be a bit complicated to do so though.
â Evan Teran
Aug 8 at 2:07
You may be interested in the experimentalconstexpr
JSON parser by Ben Deane and Jason Turner. Their experiments are titled constexpr all the things. There have been talks at C++Now 2017 (youtu.be/HMB9oXFobJc) and CppCon 2017 (youtu.be/PJwd4JLYJJY). The source code is on GitHub, but I recommend watching the talk.
â Julius
Aug 8 at 6:14
 |Â
show 1 more comment
Since this question is tagged with c++17, have you ever considered usingstd::string_view
in your implementation?std::string_view
is build withconstexpr
in mind, so it is definitely worth looking. en.cppreference.com/w/cpp/header/string_view
â HugoTeixeira
Aug 8 at 2:03
@HugoTeixeira Definitely. My plan is/was to switch to a string_view once I had the core concepts of what I was experimenting with working how I want.
â Evan Teran
Aug 8 at 2:05
Is there any reason you have to use a string? Representing regex rules (e.g. the kleene star) using operators or objects would probably be significantly easier. I believe that's what Boost.Spirit does.
â Pharap
Aug 8 at 2:05
well, "regex" is was intended as an analogy for what I want to do. As in: string -> state -> execute_state. I was hoping for a nice way to do the first part at compile time... It looks like it will be a bit complicated to do so though.
â Evan Teran
Aug 8 at 2:07
You may be interested in the experimentalconstexpr
JSON parser by Ben Deane and Jason Turner. Their experiments are titled constexpr all the things. There have been talks at C++Now 2017 (youtu.be/HMB9oXFobJc) and CppCon 2017 (youtu.be/PJwd4JLYJJY). The source code is on GitHub, but I recommend watching the talk.
â Julius
Aug 8 at 6:14
Since this question is tagged with c++17, have you ever considered using
std::string_view
in your implementation? std::string_view
is build with constexpr
in mind, so it is definitely worth looking. en.cppreference.com/w/cpp/header/string_viewâ HugoTeixeira
Aug 8 at 2:03
Since this question is tagged with c++17, have you ever considered using
std::string_view
in your implementation? std::string_view
is build with constexpr
in mind, so it is definitely worth looking. en.cppreference.com/w/cpp/header/string_viewâ HugoTeixeira
Aug 8 at 2:03
@HugoTeixeira Definitely. My plan is/was to switch to a string_view once I had the core concepts of what I was experimenting with working how I want.
â Evan Teran
Aug 8 at 2:05
@HugoTeixeira Definitely. My plan is/was to switch to a string_view once I had the core concepts of what I was experimenting with working how I want.
â Evan Teran
Aug 8 at 2:05
Is there any reason you have to use a string? Representing regex rules (e.g. the kleene star) using operators or objects would probably be significantly easier. I believe that's what Boost.Spirit does.
â Pharap
Aug 8 at 2:05
Is there any reason you have to use a string? Representing regex rules (e.g. the kleene star) using operators or objects would probably be significantly easier. I believe that's what Boost.Spirit does.
â Pharap
Aug 8 at 2:05
well, "regex" is was intended as an analogy for what I want to do. As in: string -> state -> execute_state. I was hoping for a nice way to do the first part at compile time... It looks like it will be a bit complicated to do so though.
â Evan Teran
Aug 8 at 2:07
well, "regex" is was intended as an analogy for what I want to do. As in: string -> state -> execute_state. I was hoping for a nice way to do the first part at compile time... It looks like it will be a bit complicated to do so though.
â Evan Teran
Aug 8 at 2:07
You may be interested in the experimental
constexpr
JSON parser by Ben Deane and Jason Turner. Their experiments are titled constexpr all the things. There have been talks at C++Now 2017 (youtu.be/HMB9oXFobJc) and CppCon 2017 (youtu.be/PJwd4JLYJJY). The source code is on GitHub, but I recommend watching the talk.â Julius
Aug 8 at 6:14
You may be interested in the experimental
constexpr
JSON parser by Ben Deane and Jason Turner. Their experiments are titled constexpr all the things. There have been talks at C++Now 2017 (youtu.be/HMB9oXFobJc) and CppCon 2017 (youtu.be/PJwd4JLYJJY). The source code is on GitHub, but I recommend watching the talk.â Julius
Aug 8 at 6:14
 |Â
show 1 more comment
1 Answer
1
active
oldest
votes
up vote
18
down vote
Let's reduce this:
constexpr void f(int i)
constexpr int j = i; // error
int main()
constexpr int i = 0;
constexpr int j = i; // OK
Function parameters are never constexpr
, so i
inside f
is not a constant expression and can't be used to initialize j
. Once you pass something through a function parameter, the constexpr-ness is lost.
That certainly sounds about right :-/ Certainly I've read about people doing clever tricks to do compile time parsing usingconstexpr
, is there something people are doing to get around this?
â Evan Teran
Aug 7 at 23:40
1
The general workaround is to get the value into a template non-type parameter (or a pack thereof). For string literals this is particularly difficult and AFAIK requires a non-standard extension (supported by GCC and Clang only) before C++20.
â T.C.
Aug 7 at 23:45
OK, sounds like I need to look into things like this: stackoverflow.com/questions/15858141/â¦
â Evan Teran
Aug 7 at 23:46
2
OK, I think you're answer is fundamentally right... but your reduced code is not quite representative. I'm looking at something which makes no sense to me right now: this works: constexpr size_t Func(constexpr_string input) if(input[0] == 'X') return 1; return 0; this doesn't: constexpr size_t Func(constexpr_string input) constexpr char ch = input[0]; if(ch == 'X') return 1; return 0;
â Evan Teran
Aug 8 at 0:14
2
constexpr size_t compiled_size = calculate_size(input);
is valid becauseinput
is constexpr here andcalculate_size(input)
, considered as a whole, is a valid constant expression. Insidecalculate_size
, its parameter isn't constexpr, but that doesn't stop the whole function call expression from being constexpr.
â T.C.
Aug 8 at 1:32
 |Â
show 6 more comments
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
18
down vote
Let's reduce this:
constexpr void f(int i)
constexpr int j = i; // error
int main()
constexpr int i = 0;
constexpr int j = i; // OK
Function parameters are never constexpr
, so i
inside f
is not a constant expression and can't be used to initialize j
. Once you pass something through a function parameter, the constexpr-ness is lost.
That certainly sounds about right :-/ Certainly I've read about people doing clever tricks to do compile time parsing usingconstexpr
, is there something people are doing to get around this?
â Evan Teran
Aug 7 at 23:40
1
The general workaround is to get the value into a template non-type parameter (or a pack thereof). For string literals this is particularly difficult and AFAIK requires a non-standard extension (supported by GCC and Clang only) before C++20.
â T.C.
Aug 7 at 23:45
OK, sounds like I need to look into things like this: stackoverflow.com/questions/15858141/â¦
â Evan Teran
Aug 7 at 23:46
2
OK, I think you're answer is fundamentally right... but your reduced code is not quite representative. I'm looking at something which makes no sense to me right now: this works: constexpr size_t Func(constexpr_string input) if(input[0] == 'X') return 1; return 0; this doesn't: constexpr size_t Func(constexpr_string input) constexpr char ch = input[0]; if(ch == 'X') return 1; return 0;
â Evan Teran
Aug 8 at 0:14
2
constexpr size_t compiled_size = calculate_size(input);
is valid becauseinput
is constexpr here andcalculate_size(input)
, considered as a whole, is a valid constant expression. Insidecalculate_size
, its parameter isn't constexpr, but that doesn't stop the whole function call expression from being constexpr.
â T.C.
Aug 8 at 1:32
 |Â
show 6 more comments
up vote
18
down vote
Let's reduce this:
constexpr void f(int i)
constexpr int j = i; // error
int main()
constexpr int i = 0;
constexpr int j = i; // OK
Function parameters are never constexpr
, so i
inside f
is not a constant expression and can't be used to initialize j
. Once you pass something through a function parameter, the constexpr-ness is lost.
That certainly sounds about right :-/ Certainly I've read about people doing clever tricks to do compile time parsing usingconstexpr
, is there something people are doing to get around this?
â Evan Teran
Aug 7 at 23:40
1
The general workaround is to get the value into a template non-type parameter (or a pack thereof). For string literals this is particularly difficult and AFAIK requires a non-standard extension (supported by GCC and Clang only) before C++20.
â T.C.
Aug 7 at 23:45
OK, sounds like I need to look into things like this: stackoverflow.com/questions/15858141/â¦
â Evan Teran
Aug 7 at 23:46
2
OK, I think you're answer is fundamentally right... but your reduced code is not quite representative. I'm looking at something which makes no sense to me right now: this works: constexpr size_t Func(constexpr_string input) if(input[0] == 'X') return 1; return 0; this doesn't: constexpr size_t Func(constexpr_string input) constexpr char ch = input[0]; if(ch == 'X') return 1; return 0;
â Evan Teran
Aug 8 at 0:14
2
constexpr size_t compiled_size = calculate_size(input);
is valid becauseinput
is constexpr here andcalculate_size(input)
, considered as a whole, is a valid constant expression. Insidecalculate_size
, its parameter isn't constexpr, but that doesn't stop the whole function call expression from being constexpr.
â T.C.
Aug 8 at 1:32
 |Â
show 6 more comments
up vote
18
down vote
up vote
18
down vote
Let's reduce this:
constexpr void f(int i)
constexpr int j = i; // error
int main()
constexpr int i = 0;
constexpr int j = i; // OK
Function parameters are never constexpr
, so i
inside f
is not a constant expression and can't be used to initialize j
. Once you pass something through a function parameter, the constexpr-ness is lost.
Let's reduce this:
constexpr void f(int i)
constexpr int j = i; // error
int main()
constexpr int i = 0;
constexpr int j = i; // OK
Function parameters are never constexpr
, so i
inside f
is not a constant expression and can't be used to initialize j
. Once you pass something through a function parameter, the constexpr-ness is lost.
answered Aug 7 at 23:36
T.C.
101k13202306
101k13202306
That certainly sounds about right :-/ Certainly I've read about people doing clever tricks to do compile time parsing usingconstexpr
, is there something people are doing to get around this?
â Evan Teran
Aug 7 at 23:40
1
The general workaround is to get the value into a template non-type parameter (or a pack thereof). For string literals this is particularly difficult and AFAIK requires a non-standard extension (supported by GCC and Clang only) before C++20.
â T.C.
Aug 7 at 23:45
OK, sounds like I need to look into things like this: stackoverflow.com/questions/15858141/â¦
â Evan Teran
Aug 7 at 23:46
2
OK, I think you're answer is fundamentally right... but your reduced code is not quite representative. I'm looking at something which makes no sense to me right now: this works: constexpr size_t Func(constexpr_string input) if(input[0] == 'X') return 1; return 0; this doesn't: constexpr size_t Func(constexpr_string input) constexpr char ch = input[0]; if(ch == 'X') return 1; return 0;
â Evan Teran
Aug 8 at 0:14
2
constexpr size_t compiled_size = calculate_size(input);
is valid becauseinput
is constexpr here andcalculate_size(input)
, considered as a whole, is a valid constant expression. Insidecalculate_size
, its parameter isn't constexpr, but that doesn't stop the whole function call expression from being constexpr.
â T.C.
Aug 8 at 1:32
 |Â
show 6 more comments
That certainly sounds about right :-/ Certainly I've read about people doing clever tricks to do compile time parsing usingconstexpr
, is there something people are doing to get around this?
â Evan Teran
Aug 7 at 23:40
1
The general workaround is to get the value into a template non-type parameter (or a pack thereof). For string literals this is particularly difficult and AFAIK requires a non-standard extension (supported by GCC and Clang only) before C++20.
â T.C.
Aug 7 at 23:45
OK, sounds like I need to look into things like this: stackoverflow.com/questions/15858141/â¦
â Evan Teran
Aug 7 at 23:46
2
OK, I think you're answer is fundamentally right... but your reduced code is not quite representative. I'm looking at something which makes no sense to me right now: this works: constexpr size_t Func(constexpr_string input) if(input[0] == 'X') return 1; return 0; this doesn't: constexpr size_t Func(constexpr_string input) constexpr char ch = input[0]; if(ch == 'X') return 1; return 0;
â Evan Teran
Aug 8 at 0:14
2
constexpr size_t compiled_size = calculate_size(input);
is valid becauseinput
is constexpr here andcalculate_size(input)
, considered as a whole, is a valid constant expression. Insidecalculate_size
, its parameter isn't constexpr, but that doesn't stop the whole function call expression from being constexpr.
â T.C.
Aug 8 at 1:32
That certainly sounds about right :-/ Certainly I've read about people doing clever tricks to do compile time parsing using
constexpr
, is there something people are doing to get around this?â Evan Teran
Aug 7 at 23:40
That certainly sounds about right :-/ Certainly I've read about people doing clever tricks to do compile time parsing using
constexpr
, is there something people are doing to get around this?â Evan Teran
Aug 7 at 23:40
1
1
The general workaround is to get the value into a template non-type parameter (or a pack thereof). For string literals this is particularly difficult and AFAIK requires a non-standard extension (supported by GCC and Clang only) before C++20.
â T.C.
Aug 7 at 23:45
The general workaround is to get the value into a template non-type parameter (or a pack thereof). For string literals this is particularly difficult and AFAIK requires a non-standard extension (supported by GCC and Clang only) before C++20.
â T.C.
Aug 7 at 23:45
OK, sounds like I need to look into things like this: stackoverflow.com/questions/15858141/â¦
â Evan Teran
Aug 7 at 23:46
OK, sounds like I need to look into things like this: stackoverflow.com/questions/15858141/â¦
â Evan Teran
Aug 7 at 23:46
2
2
OK, I think you're answer is fundamentally right... but your reduced code is not quite representative. I'm looking at something which makes no sense to me right now: this works: constexpr size_t Func(constexpr_string input) if(input[0] == 'X') return 1; return 0; this doesn't: constexpr size_t Func(constexpr_string input) constexpr char ch = input[0]; if(ch == 'X') return 1; return 0;
â Evan Teran
Aug 8 at 0:14
OK, I think you're answer is fundamentally right... but your reduced code is not quite representative. I'm looking at something which makes no sense to me right now: this works: constexpr size_t Func(constexpr_string input) if(input[0] == 'X') return 1; return 0; this doesn't: constexpr size_t Func(constexpr_string input) constexpr char ch = input[0]; if(ch == 'X') return 1; return 0;
â Evan Teran
Aug 8 at 0:14
2
2
constexpr size_t compiled_size = calculate_size(input);
is valid because input
is constexpr here and calculate_size(input)
, considered as a whole, is a valid constant expression. Inside calculate_size
, its parameter isn't constexpr, but that doesn't stop the whole function call expression from being constexpr.â T.C.
Aug 8 at 1:32
constexpr size_t compiled_size = calculate_size(input);
is valid because input
is constexpr here and calculate_size(input)
, considered as a whole, is a valid constant expression. Inside calculate_size
, its parameter isn't constexpr, but that doesn't stop the whole function call expression from being constexpr.â T.C.
Aug 8 at 1:32
 |Â
show 6 more comments
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51736678%2fc17-constexpr-string-parsing%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Since this question is tagged with c++17, have you ever considered using
std::string_view
in your implementation?std::string_view
is build withconstexpr
in mind, so it is definitely worth looking. en.cppreference.com/w/cpp/header/string_viewâ HugoTeixeira
Aug 8 at 2:03
@HugoTeixeira Definitely. My plan is/was to switch to a string_view once I had the core concepts of what I was experimenting with working how I want.
â Evan Teran
Aug 8 at 2:05
Is there any reason you have to use a string? Representing regex rules (e.g. the kleene star) using operators or objects would probably be significantly easier. I believe that's what Boost.Spirit does.
â Pharap
Aug 8 at 2:05
well, "regex" is was intended as an analogy for what I want to do. As in: string -> state -> execute_state. I was hoping for a nice way to do the first part at compile time... It looks like it will be a bit complicated to do so though.
â Evan Teran
Aug 8 at 2:07
You may be interested in the experimental
constexpr
JSON parser by Ben Deane and Jason Turner. Their experiments are titled constexpr all the things. There have been talks at C++Now 2017 (youtu.be/HMB9oXFobJc) and CppCon 2017 (youtu.be/PJwd4JLYJJY). The source code is on GitHub, but I recommend watching the talk.â Julius
Aug 8 at 6:14