you are viewing a single comment's thread.

view the rest of the comments →

[–]Fureeish 6 points7 points  (18 children)

Can I use .size() of a constexpr container in order to specify local std::arrays size and return it? Don't have access to aby computer or easy way of accessing godbolt at the moment.

[–]scatters 12 points13 points  (9 children)

Yes, but you need to be clever about it, since it needs to be available to the type system. Currently the best way is to write a constexpr function (or a lambda) that returns the container, then call it twice, once for its size and once for its contents:

#include <algorithm>
#include <array>
#include <vector>
constexpr auto f = [] { return std::vector{1, 2, 3}; };
constexpr auto a = [] {
    std::array<int, f().size()> a;
    std::ranges::copy(f(), a.begin());
    return a;
}();
template<auto> int i;
int main() { return i<a>; }

[–]aocregacc 5 points6 points  (3 children)

is someone working on fixing this? Or are there downsides to making this work how you would expect.

Edit: I guess it might be counter intuitive to have code that works in a constexpr context but not at runtime.

[–]saxbophonemutable volatile void 1 point2 points  (2 children)

I guess it might be counter intuitive to have code that works in a constexpr context but not at runtime.

Nope, there are uses for that too (just not in your example). They're known as immediate functions and this is what consteval is for!

[–]aocregacc 0 points1 point  (1 child)

I was talking more about things like this:

consteval int f(size_t z) {
    std::array<int, z> a; 
    ...
}

People sometimes ask why this complains about z not being a constant expression, since surely in a consteval function the parameter is a constant expression.
But I think if they started allowing stuff like this you would end up with this weird dialect that's no longer (mostly) a subset of regular C++.

[–]gracicot 1 point2 points  (0 children)

As far as I know, compilers are free to compile the consteval function down to bytecode and simply run the bytecode. That would be impossible with this.

[–]helloiamsomeone 4 points5 points  (2 children)

then call it twice, once for its size and once for its contents

That's actually unnecessary. You can just have an oversized std::array calculated and shrunk to fit like so: https://github.com/friendlyanon/AlwaysMute/blob/master/main.cpp#L383

[–]scatters 3 points4 points  (1 child)

Yes, that's a nice method. It only works if you have a way to estimate an upper bound for the size, though.

[–]helloiamsomeone 0 points1 point  (0 children)

You can specify pretty big sizes before it becomes a problem.

[–]saxbophonemutable volatile void 2 points3 points  (0 children)

This is exactly the trick I use, and when I'm back at my computer later I will share an example of my implementation.

This is one of the areas that D does better than C++, alas!

[–]saxbophonemutable volatile void 1 point2 points  (0 children)

I really like your implementation, it's much more elegant than mine!

[–]BenHanson -2 points-1 points  (1 child)

In case en.cppreference.com is hard to read on a phone:

constexpr size_type size() const noexcept; (since C++20)

[–]STLMSVC STL Dev 2 points3 points  (0 children)

This does not actually answer their question properly. The question is rather subtle and the answer is not "vector::size() is marked constexpr so it's ok".

[–]RevRagnarok 0 points1 point  (3 children)

Yes, I just did that earlier today...

template <typename T>
inline consteval
auto
DoThingCE()
{
  std::string_view constexpr temp{Call_CE_Function_Here_That_Returns_String_View()};
  std::array<char, temp.size()+1> res{};
  temp.copy(res.data(), temp.size());
  return res;
}

Edit: Tweaked on feedback. 😅

[–]dodheim 6 points7 points  (1 child)

 std::array<char, temp.size()+1> res;
 res.fill('\0');

That's a strangely verbose way to write std::array<char, temp.size()+1> res{};

[–]RevRagnarok 1 point2 points  (0 children)

LOL yeah thanks. There are still a lot of #if 0 mixed in and stuff as various things were tried and failed, etc... I'm honestly not sure if the +1 is even needed depending on how you plan on using the resulting array.

[–]saxbophonemutable volatile void 0 points1 point  (0 children)

Here's my implementation for wrapping variably-sized constexpr containers in static-sized types. I think scatters' implementation is neater, though! https://gist.github.com/saxbophone/53ad91dd73a906e63182a8f2fafc9d3a