It is very long standing problem of C++ that you cannot use string literals as template parameters.
I acknowledge that macros are bad, however..
C++ lambdas have a special property of generating anonymous unique types.
Therefore a scope in which to create additional types.
This seems to be quite useful. It seems like producing types (or functions) within lambdas within macros provides template-like powers, and not in the bad old way that macros on their own do.
I'm not sure where all this will go, but here is a start:
#include <stdio.h>
#include <string>
#define STRING_TEMPLATE_FUNCTION(str) \
[]() { struct Type { static const char* Function() { return str; } }; return Type::Function; }()
#define STRING_TEMPLATE_CLASS(str) \
[=]() { struct Type : std::string { using std::string::operator=; Type() : std::string(str) { } }; return []{ return Type();}(); }()
int main()
{
auto foo = STRING_TEMPLATE_FUNCTION("foo");
auto bar = STRING_TEMPLATE_CLASS("bar");
auto bar2 = STRING_TEMPLATE_CLASS("bar2");
printf("%s\n", foo());
printf("%s\n", bar.c_str());
printf("%s\n", bar2.c_str());
bar = bar2;
printf("%s\n", bar.c_str());
}
Hey Jay, I think string literal template parameters are possible in C++20 and above (with a little help). Here is an example from some code I wrote last year:
ReplyDelete#if _HAS_CXX20
// Helper to allow string literals as template arguments
template
struct StringLiteral
{
constexpr StringLiteral(const char(&str)[N])
{
std::copy_n(str, N, value);
}
constexpr operator const char* () const { return value; }
char value[N];
auto operator<=>(const StringLiteral& other) const = default;
bool operator==(const StringLiteral& other) const = default;
};
/// @brief Provide a typed key (encoding both the string key and the type of the value) for meta data lookup.
template
struct TypedKey
{
constexpr static auto name = Name;
typedef T type;
};
/// @brief TypedKey for HResultKeys.
typedef TypedKey HResultKey;
/// @brief TypedKey for stack traces.
typedef TypedKey StackKey;
#endif _HAS_CXX20