C++17 constexpr string parsing

The name of the pictureThe name of the pictureThe name of the pictureClash 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 same
constexpr 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:






share|improve this question






















  • 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










  • 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















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 same
constexpr 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:






share|improve this question






















  • 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










  • 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













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 same
constexpr 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:






share|improve this question














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 same
constexpr 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:








share|improve this question













share|improve this question




share|improve this question








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 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










  • 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

















  • 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










  • 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
















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













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.






share|improve this answer




















  • 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




    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 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










Your Answer





StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















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






























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.






share|improve this answer




















  • 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




    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 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














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.






share|improve this answer




















  • 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




    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 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












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.






share|improve this answer












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.







share|improve this answer












share|improve this answer



share|improve this answer










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 using constexpr, 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 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
















  • 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




    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 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















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












 

draft saved


draft discarded


























 


draft saved


draft discarded














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













































































Popular posts from this blog

How to check contact read email or not when send email to Individual?

Displaying single band from multi-band raster using QGIS

How many registers does an x86_64 CPU actually have?