On Monday, 17 July 2017 16:44:01 UTC+3, rep_movsd wrote:
> I'm writing a library that does compile time parsing, creating a list.
> The only way I am able to get it to work right now is by using a std::array
> of my Node structure as a "statically allocated pool" and using
> integer indexes as "pointers" into that array.
>
> This works great, but I am forced to fix the size of the array.
Might be worthy exercise but further posted code does not quite reflect what
you wrote above.
You plan to pass a copy of NullNode to its own constructor? Creating such
constexpr temporaries and taking references to those won't work.
>
>
> constexpr Node parse(const char* text)
> {
> if(text)
> {
> text = eatSpace(text);
> if(isAlpha(*text))
> {
> Symbol symTag = eatAlpha(text);
> return Node(symTag, parse(symTag.pEnd));
Again same thing as on previous case but this time recursive return values
passed by value and then taken references. :D
> }
> }
> return NullNode;
> }
>
> void dumpNode(const Node &n, int indent = 0)
> {
> if(&n.child != &NullNode)
> {
> cerr << n.tag.getText() << endl;
> dumpNode(n.child, indent + 1);
> }
> }
>
>
> int main()
> {
> constexpr Node node = parse("attr battr cattr");
> dumpNode(node);
> }
>
> When compiling:
>
> $ g++ --std=c++14 -DSPT_DEBU main4.cpp
> main4.cpp:72:48: error: 'Node{Symbol{0, 0}, child}' is not a constant expression
> constexpr const Node NullNode{NullSym, NullNode};
> ^
> main4.cpp: In function 'int main()':
> main4.cpp:101:49: in constexpr expansion of 'parse(((const char*)"attr battr cattr"))'
> main4.cpp:83:44: in constexpr expansion of 'parse(symTag.Symbol::pEnd)'
> main4.cpp:83:44: in constexpr expansion of 'parse(symTag.Symbol::pEnd)'
> main4.cpp:83:44: in constexpr expansion of 'parse(symTag.Symbol::pEnd)'
> main4.cpp:101:49: error: constexpr call flows off the end of the function
> constexpr Node node = parse("attr battr cattr");
> ^
>
> Is what I am trying even possible?
>
> I'm a bit hazy about what the lifetime of constexpr values are when you
> nest them through recursive calls
Do not try to build your list into some sort of references taken to
by-value returns of functions or by-value passed function parameters.
That is not meant to work.
>
> I'm pretty sure this should be possible. After all someone wrote a constexpr
> C compiler.
>
> All I need is some sort of dynamic data structure like a list, that
> doesnt have to be fixed in size at compile time.
>
> Thanks in advance.
Sure it is possible but it is strange how you try it.
First thing get rid of pointer algebra. Length of string literal is
known to compiler so pass around the reference to it like that:
#include <iostream>
template<size_t N> constexpr
size_t len(char const (&literal)[N])
{
return N;
}
template<size_t N> constexpr
char nth_char(char const (&literal)[N], size_t n)
{
return literal[n];
}
int main()
{
constexpr char what_we_parse[] = "attr battr cattr";
constexpr size_t l = len(what_we_parse);
constexpr char c = nth_char(what_we_parse, 5);
std::cout << "Len: " << l << " 5th: " << c << std::endl;
}
Try it. It will make your code lot simpler.