Conveniently Declaring Compile-Time Strings in C++
I haven't seen anything to match the elegance of Scott Schurr's str_const
presented at C++ Now 2012. It does require constexpr
though.
Here's how you can use it, and what it can do:
int
main()
{
constexpr str_const my_string = "Hello, world!";
static_assert(my_string.size() == 13, "");
static_assert(my_string[4] == 'o', "");
constexpr str_const my_other_string = my_string;
static_assert(my_string == my_other_string, "");
constexpr str_const world(my_string, 7, 5);
static_assert(world == "world", "");
// constexpr char x = world[5]; // Does not compile because index is out of range!
}
It doesn't get much cooler than compile-time range checking!
Both the use, and the implementation, is free of macros. And there is no artificial limit on string size. I'd post the implementation here, but I'm respecting Scott's implicit copyright. The implementation is on a single slide of his presentation linked to above.
Update C++17
In the years since I posted this answer, std::string_view
has become part of our tool chest. Here is how I would rewrite the above using string_view
:
#include <string_view>
int
main()
{
constexpr std::string_view my_string = "Hello, world!";
static_assert(my_string.size() == 13);
static_assert(my_string[4] == 'o');
constexpr std::string_view my_other_string = my_string;
static_assert(my_string == my_other_string);
constexpr std::string_view world(my_string.substr(7, 5));
static_assert(world == "world");
// constexpr char x = world.at(5); // Does not compile because index is out of range!
}
C++ string concatenation in compile time
This would work without allocating, and also compile time
#include <iostream>
#define STR_(X) #X
#define STR(X) STR_(X)
int main()
{
//constexpr std::string_view(const char*) doesn't work in some versions of gcc, but is a better alternative if the compiler supports it
constexpr const char* str = __FILE__ ":" STR(__LINE__);
std::cout << str << std::endl;
}
Turn C string literal into std::integer_sequence at compile-time with C++17
Something like this might do it:
template <size_t N, typename F, size_t... indexes>
constexpr auto make_seq_helper(F f, std::index_sequence<indexes...> is) {
return std::integer_sequence<char, (f()[indexes])...>{};
}
template <typename F>
constexpr auto make_seq(F f) {
constexpr size_t N = f().size();
using indexes = std::make_index_sequence<N>;
return make_seq_helper<N>(f, indexes{});
};
template<const char* str>
struct IntegerSequenceFromString {
private:
constexpr static auto value = make_seq([](){return std::string_view{str}; });
public:
using type = decltype(value);
};
Usage would then be:
constexpr static const char str[] = "lala";
IntegerSequenceFromString<str>::type i{};
Here is a live example of it working.
I am sure, there is a way to reduce some of this extra stuff as well, but from the assembly, it looks like we don't generate any real runtime variables: https://godbolt.org/z/f65cjGfzn
Generating compile time functions string for formatting strings with libfmt
The type of the format string and the return type of the function cannot be string_view
since the format string is constructed dynamically, using string_view
will result in a dangling pointer.
In addition, fmt::format
requires that the format string must be a constant expression. Instead, you need to use fmt::vformat
. This should work
static std::string
headerCenter(const std::string& text, const int width, const char fill) {
// build fmt string
std::string format = fmt::format("|{{0:{}^{}}}|", fill, width);
return fmt::vformat(format, fmt::make_format_args(text));
}
Demo
Related Topics
Is a String Literal in С++ Created in Static Memory
Accessing Protected Members in a Derived Class
Rand() Returns Same Values When Called Within a Single Function
C++ Lambda With Captures as a Function Pointer
Difference Between Files Written in Binary and Text Mode
What's the Best Free C++ Profiler For Windows
Generate Random Numbers Using C++11 Random Library
Dynamically Allocating an Array of Objects
Should I Use Static_Cast or Reinterpret_Cast When Casting a Void* to Whatever
What Are the Mechanics of Short String Optimization in Libc++
How to Create a Dynamic Array of Integers
How to Pad an Int With Leading Zeros When Using Cout ≪≪ Operator
C++: What Is the Size of an Object of an Empty Class