store a string in a constexpr struct - c++

Is it possible to store a string in a constexpr struct:
So far I could only come up with:
struct A
{
constexpr A(std::string_view n): m_name(n) {}
constexpr auto name(){ return m_name; }
std::string_view m_name; // This might become dangling!!
}
which is cleary only a good idea if this class is only used like this
A a = {"Hello"};
constexpr A b = {"World"};
and not like this
auto makeA(std::string n) { return A{n}; }
A a = makeA("Hello"); // Dangling internal std::string_view
I need the constexpr to construct the struct at compile time.
Is it possible to make this safer at run-time, because with std::string_view, its not.

This is not really a question of safety as much as it is a question of semantics. Nothing prevents you from doing the exact same thing at compiletime:
constexpr A blub()
{
char str[] = "asdf";
return { str };
}
Since there is no way to ever call this function in a core constant expression, a program that contains code like this is ill-formed, no diagnostic required [dcl.constexpr]/5, which really isn't any better than invoking undefined behavior at runtime…
Compiletime or not, you have to ask yourself the question: Should this struct own a string or refer to an existing string? I would strongly recommend against making your struct own a string in a runtime context and refer to an existing string in a compiletime context, even if you find a way to pull this off in theory. We're talking about completely different semantics here. Completely different semantics should generally better be modeled by different types rather than one type that completeley changes its meaning depending on context…
If you want to make a constexpr struct own a string, you'll currently have to resort to some constexpr string implementation such as, e.g., this one. Since your question is tagged with c++20, note that std::string will be useable in a constexpr context starting with C++20 [basic.string]. So, in C++20, you will be able to just have the member be an std::string…

You might do:
template<typename Char, Char... Cs>
struct CharSeq
{
static constexpr const Char s[] = {Cs..., 0}; // The unique address
};
// That template uses the extension
template<typename Char, Char... Cs>
constexpr CharSeq<Char, Cs...> operator"" _cs() {
return {};
}
See my answer from String-interning at compiletime for profiling to have MAKE_STRING macro if you cannot used the extension (Really more verbose, and hard coded limit for accepted string length).
Then
struct A
{
template <char ... Cs>
constexpr A(CharSeq<char, Cs...>) : m_name(CharSeq<char, Cs...>::s) {}
constexpr auto name(){ return m_name; }
std::string_view m_name;
};
With only valid usages similar to:
A a = {"Hello"_cs};
constexpr A b = {"World"_cs};

Related

C++17 - constexpr byte iteration for trivial types

Given my prototype for a simple hashing method:
template <typename _iterator>
constexpr uint32_t hash_impl(_iterator buf, size_t len);
Generating constexpr hashes for simple strings is pretty trivial:
template <char const* str>
constexpr uint32_t generate()
{
constexpr std::string_view strView = str;
return hash_impl(str, strView.size());
}
constexpr uint32_t generate(const std::string_view& str)
{
return hash_impl(str.begin(), str.size());
}
constexpr static char str1[] = "Hello World!";
constexpr uint32_t hash1 = generate<str1>();
constexpr std::string_view str2("Hello World!");
constexpr uint32_t hash2 = generate(str2);
I'd also like to generate constexpr hashes for a variety of simple (POD and trivial structs) types too. However, I'm not sure how to get the byte representation of these types in a constexpr-friendly way.
My naive implementation:
template <typename T, typename = std::enable_if_t< std::is_standard_layout_v<T> && !std::is_pointer_v<T> >>
constexpr uint32_t generate(const T& value)
{
return hash_impl(reinterpret_cast<const std::byte*>(&value), sizeof(T));
}
falls over because &value and reinterpret_cast<> breaks constexpr rules. I've searched for a workaround, but other answers on the site indicate that it's not possible.
Worst case scenario, I can manually check for and hash specific types as so:
template <typename T, typename = std::enable_if_t< std::is_standard_layout_v<T> && !std::is_pointer_v<T> >>
constexpr uint32_t generate(const T& value)
{
if constexpr (std::is_same_v<T, int32_t> || std::is_same_v<T, uint32_t>)
{
char buf[] =
{
static_cast<char>(value >> 0),
static_cast<char>(value >> 8),
static_cast<char>(value >> 16),
static_cast<char>(value >> 24)
};
return generate(buf, 4);
}
else if constexpr (/* etc... */)
// ...
}
but this falls over as soon as I try to implement this for something like a float (which has no bitwise operators) or for trivial custom types (eg, struct foo { int a; }; unless I write an extra code block for foo).
I feel like I must be overlooking something simple, but I can't find any stl utility or think of any fancy template trick that would suit. Perhaps there's something in C++20 or C++23 that I'm not aware of?
It is not possible in C++17. In C++20 you can use std::bit_cast to get the object representation of a trivially copyable type:
auto object_representation = std::bit_cast<std::array<std::byte, sizeof(T)>>(value);
(Technically you can argue about whether or not it is guaranteed that std::array has no additional padding/members that would make this ill-formed, but in practice that is not a concern.)
You can then pass the array as a pointer/size pair to the hash implementation. You should probably also add
static_assert(std::has_unique_object_representations_v<T>);
If the assertion fails you will have no guarantee that objects with same value will have the same object representation and same hash.
Btw. std::is_standard_layout_v is not the property you need here. The property that you need to verify is std::is_trivially_copyable_v. Being standard-layout is neither sufficient nor necessary to be able to inspect and use the object representation like this.

Gather Addresses of all Static C Strings at Compile Time

Let's say I have a function like
void foo(const char* bar, ...)
And it has been called in multiple places.
Is it possible to gather addresses of all static strings that are known at compile time in main()?
For example, foo("abc"), I want in main() to be able to get the address of "abc". If someone calls foo(someVariable), the address of someVariable might not be known, and so it can be ignored.
Is it possible?
If you agree to use registration, you might do something like
// Would contain each registered string.
std::vector<const char*>& registered_vector()
{
static std::vector<const char*> v;
return v;
}
bool Register(const char* s)
{
registered_vector().push_back(s);
return true;
}
// Class which holds the unique pointer as buffer.
template <typename Char, Char... Cs>
struct static_string
{
static constexpr Char s[] = {Cs..., 0};
};
template <typename Char, Char... Cs>
constexpr Char static_string<Char, Cs...>::s[];
// string literal operator templates are a GNU extension
// MACRO can replace the operator to avoid that extension.
template <typename Char, Char... Cs>
static_string<Char, Cs...> operator ""_ss()
{
static_string<Char, Cs...> res;
static const bool dummy = Register(res.s); // Register only once :-)
static_cast<void>(dummy); // Avoid warning for unused variable
return res;
}
And now, test it:
int main() {
"Hello"_ss;
"World"_ss;
"Hello"_ss;
"Hi"_ss;
"42"_ss;
for (const auto s : registered_vector()) {
std::cout << s << std::endl;
}
}
Demo
Is it possible to gather addresses of all static strings that are known at compile time in main()?
At compile time strings from other translation units are unavailable.
You can dump string literals from your executable or shared library using readelf -W -p .rodata <executable> command.

Equivalent ternary operator for constexpr if?

Maybe I missed something, but I can't find any hints: is there a constexpr ternary operator in C++17 equivalent to constexpr-if?
template<typename Mode>
class BusAddress {
public:
explicit constexpr BusAddress(Address device) :
mAddress(Mode::write ? (device.mDevice << 1) : (device.mDevice << 1) | 0x01) {}
private:
uint8_t mAddress = 0;
};
No, there is no constexepr conditional operator. But you could wrap the whole thing in a lambda and immediately evaluate it (an IIFE):
template<typename Mode>
class BusAddress {
public:
explicit constexpr BusAddress(Address device)
: mAddress([&]{
if constexpr (Mode::write) {
return device.mDevice << 1;
}
else {
return (device.mDevice << 1) | 0x01;
}
}())
{ }
private:
uint8_t mAddress = 0;
};
It may not be the sexiest code ever, but it gets the job done. Note that lambdas are constexpr by default where possible as of N4487 and P0170.
You seem to be acting under the belief that if constexpr is a performance optimization. It isn't. If you put a constant expression in a ?: clause, any compiler worth using will figure out what it resolves to and remove the condition. So the code as you have written it will almost certainly compile down to a single option, for a particular Mode.
The principle purpose of if constexpr is to eliminate the other branch entirely. That is, the compiler doesn't even check to see if it is syntactically valid. This would be for something where you if constexpr(is_default_constructible_v<T>), and if it is true, you do T(). With a regular if statement, if T isn't default constructible, T() will still have to be syntactically valid code even if the surrounding if clause is a constant expression. if constexpr removes that requirement; the compiler will discard statements that are not in the other condition.
This becomes even more complicated for ?:, because the expression's type is based on the types of the two values. As such, both expressions need to be legal expressions, even if one of them is never evaluated. A constexpr form of ?: would presumably discard the alternative that is not taken at compile time. And therefore the expression's type should really only be based on one of them.
That a very different kind of thing.
Accepted answer can also be translated into a template function for convenience:
#include <type_traits>
#include <utility>
template <bool cond_v, typename Then, typename OrElse>
decltype(auto) constexpr_if(Then&& then, OrElse&& or_else) {
if constexpr (cond_v) {
return std::forward<Then>(then);
} else {
return std::forward<OrElse>(or_else);
}
}
// examples
struct ModeFalse { static constexpr bool write = false; };
struct ModeTrue { static constexpr bool write = true; };
struct A {};
struct B {};
template <typename Mode>
auto&& test = constexpr_if<Mode::write>(A{}, B{});
static_assert(std::is_same_v<A&&, decltype(test<ModeTrue>)>);
static_assert(std::is_same_v<B&&, decltype(test<ModeFalse>)>);
const A a;
B b;
template <typename Mode>
auto&& test2 = constexpr_if<Mode::write>(a, b);
static_assert(std::is_same_v<const A&, decltype(test2<ModeTrue>)>);
static_assert(std::is_same_v<B&, decltype(test2<ModeFalse>)>);

Why should I prefer static constexpr int in a class over enum for class-level integral constants?

C++17 Update:
static constexpr variables are implicitly inline so there's no external definition necessary.
Original question:
Let's say I have a list of constants such as
struct Cls {
static constexpr int N = 32;
static constexpr int M = 64;
};
This of course suggests that I add definitions for these to avoid ODR-usage issues that may occur so I need:
constexpr int Cls::N;
constexpr int Cls::M;
Why should I prefer this over
struct Cls {
enum : int {
N = 32,
M = 64
};
};
Which saves me of the ODR-usage headaches since N and M are more truly just constants and not objects in their own right (a bigger deal if this is header-only) and is shorter. I could explicitly specify the type enum : long long or whatever if need be. What is the advantage of the first?
One difference is that you can take the address of a static constexpr but not of an enum.
Another is that constexpr isn't supported by older versions of the language (it was introduced in C++11).
I'd use enum only if the values belong together. I'd also give the enum a name that describes that relationship. I wouldn't use an enum for defining unrelated constants.
Perhaps no advantage for your usage because you're just using simple fixed integer values.
But, [AFAIK] constexpr can be more general as it allows initialization from anything that can be evaluated at compile time.
From type_traits:
/// integral_constant
template<typename _Tp, _Tp __v>
struct integral_constant
{
static constexpr _Tp value = __v;
typedef _Tp value_type;
typedef integral_constant<_Tp, __v> type;
constexpr operator value_type() const { return value; }
#if __cplusplus > 201103L
#define __cpp_lib_integral_constant_callable 201304
constexpr value_type operator()() const { return value; }
#endif
};
Thus, constexpr has usage in metaprogramming.
The following is a bit rough.
If you had a function like:
constexpr unsigned
bitmask(int bitno)
{
return 1u << bitno;
}
You might find a usage such as:
constexpr unsigned BIT_0 = bitmask(0);
constexpr unsigned BIT_1 = bitmask(1);
The reason I would give you is that using enum { } for constants is a misuse of the term enum. You're not enumerating anything. It's a common misuse, granted; it has its practical advantages; but it's just kind of wrong. There should be a way to say "this is just a compile-time constant and nothing else". constexpr isn't that thing either, but it's closer than enum. And it's rightly the case that you can't enum floating-point values.
That being said - I often use enums for constants myself, when I want to protect myself against people writing something like void* ptr = &some_constant_value; std::cout << ptr;

C++ explicit return type template specialisation

This is a follow up on this (more general) question: previous question. A partial answer to the present question is given here: partial answer to the present question.
I am interested in explicit specialisation of the return type based on the template argument. While the answer presented above provides a solution to the problem, I believe that there is a more elegant way of solving the problem using C++11/14 techniques:
template<int N> auto getOutputPort2();
template<> auto getOutputPort2<0>();
template<> auto getOutputPort2<1>();
template<>
auto getOutputPort2<0>()
{
return std::unique_ptr<int>(new int(10));
}
template<>
auto getOutputPort2<1>()
{
return std::unique_ptr<string>(new string("asdf"));
}
The code above compiles and works as expected using gcc 4.8.3 (with -std=c++0x flag). However, it issues the following warning:
getOutputPort2 function uses auto type specifier without trailing return type.
From my understanding this will become part of the C++14 standard. However, is there a way of implementing the functionality above in C++11? Can decltype be used here?
EDIT. Following the comments below, I would also like to ask an additional question. Is the code above valid from the perspective of the C++14 standard? If not, why not?
You can extend the idea of a helper template class, and put pretty much everything in there. It's not exactly pretty for whoever has to write the specialisations, but it's very convenient for the user, who can just call f<0>, f<1>, etc. It doesn't really need decltype, but decltype does make it quite a bit easier to write.
template <int N>
struct f_impl;
template <int N>
decltype(f_impl<N>::impl()) f()
{ return f_impl<N>::impl(); }
template <> struct f_impl<0> {
static int impl() { return 1; }
};
template <> struct f_impl<1> {
static const char *impl() { return " Hello, world!"; }
};
int main() {
std::puts(f<1>() + f<0>());
}
You might be able to make it a bit more manageable with macros: instead of
template <> struct f_impl<1> {
static const char *impl() { return " Hello, world!"; }
};
you could write something along the lines of
#define DEFINE_F(N, Result) \
template <> struct f_impl<N> { \
static Result impl(); \
}; \
Result f_impl<N>::impl()
DEFINE_F(1, const char *) {
return " Hello, world!";
}
but I'm not convinced it's an improvement over just writing out f_impl (with a better name) in full.