Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to initialize a complete member array only in a constexpr context ?

12 views
Skip to first unread message

Timothy Madden

unread,
Sep 22, 2022, 6:27:28 AM9/22/22
to Timothy Madden
Hello

I am writing a class template for fixed capacity strings:
basic_static_string<SIZE, char, char_traits<char>>
(similar to the one in boost, but my company doesn't use newest version of
boost yet). I use C++14 at work, and the only data members of my class
template are:
std::size_t len;
char buffer[SIZE];

When I instantiate and construct a static string, like:
static_string<256u>("Delta")
I would like to only initialize the needed characters (characters 0 to 5)
and leave the other 251 characters uninitialized.

I would like my class to be constexpr, since there is no memory
allocation. However, somehow a constexpr constructor must use the member-
initializers to initialize the entire object.

Is there any way to use std::is_constant_evaluated() to completely
initialize the member array in a constexpr context, and partially
initialized it in a run-time context ?

This would be easy to do inside a function body with an if statement, but
in a member-initializer for a constructor it is not. I tried to use
is_constant_evaluated() in a template argument, but then it will always
return true. Why is the standard defined like that ? It makes
is_constant_evaluated() useless, when you actually need it...

--
Thank you,
Timothy Madden

Juha Nieminen

unread,
Sep 22, 2022, 7:14:47 AM9/22/22
to
Timothy Madden <termin...@gmail.com> wrote:
> Hello
>
> I am writing a class template for fixed capacity strings:
> basic_static_string<SIZE, char, char_traits<char>>
> (similar to the one in boost, but my company doesn't use newest version of
> boost yet). I use C++14 at work, and the only data members of my class
> template are:
> std::size_t len;
> char buffer[SIZE];
>
> When I instantiate and construct a static string, like:
> static_string<256u>("Delta")
> I would like to only initialize the needed characters (characters 0 to 5)
> and leave the other 251 characters uninitialized.
>
> I would like my class to be constexpr, since there is no memory
> allocation. However, somehow a constexpr constructor must use the member-
> initializers to initialize the entire object.

You mean that you wouldn't want to have the initializer that I have marked
below with "// THIS"?

//---------------------------------------------------------------------
#include <cstddef>

template<std::size_t kCapacity>
class StaticString
{
char mData[kCapacity];
std::size_t mLength;

public:
template<std::size_t kStrLength>
constexpr StaticString(const char(&initStr)[kStrLength]):
mData{}, // THIS
mLength(kStrLength - 1)
{
for(std::size_t i = 0; i < kStrLength; ++i)
mData[i] = initStr[i];
}

constexpr const char* c_str() const { return mData; }
};

#include <iostream>
int main()
{
constexpr StaticString<256> str("hello world");

std::cout << "\"" << str.c_str() << "\"\n";
}
//---------------------------------------------------------------------

Timothy Madden

unread,
Sep 22, 2022, 10:32:30 AM9/22/22
to
On Thu, 22 Sep 2022 11:14:21 -0000 (UTC), Juha Nieminen wrote:

> Timothy Madden <termin...@gmail.com> wrote:
[...]
>
> You mean that you wouldn't want to have the initializer that I have
> marked below with "// THIS"?
>
> //---------------------------------------------------------------------
> #include <cstddef>
>
> template<std::size_t kCapacity>
> class StaticString {
> char mData[kCapacity];
> std::size_t mLength;
>
> public:
> template<std::size_t kStrLength>
> constexpr StaticString(const char(&initStr)[kStrLength]):
> mData{}, // THIS mLength(kStrLength - 1)
> {
> for(std::size_t i = 0; i < kStrLength; ++i)
> mData[i] = initStr[i];
> }
>
> constexpr const char* c_str() const { return mData; }
> };
[...]


The member-initializer
: mData { }
zeroes-out 256 characters, when I only need to initialize 12 (for "hello
world").

This is the right thing to do in a constexpr context, but in a run-time
context I want to avoid it.

So my thought was to use std::is_constant_evaluated() somehow and only
apply the initializer if the function returns true. But the syntax of a
member-initializer doesn't seem to allow it.
0 new messages