Monday, August 21, 2023

string literals as template parameters, sort of

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());

}


1 comment:

  1. 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:

    #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

    ReplyDelete