我已经编写了一些代码,通过使用const char*int转换为constexpr,因此可以将const char*用作模板参数。这是代码:

#include <iostream>

class conststr
{
    public:
        template<std::size_t N>
        constexpr conststr(const char(&STR)[N])
        :string(STR), size(N-1)
        {}

        constexpr conststr(const char* STR, std::size_t N)
        :string(STR), size(N)
        {}

        constexpr char operator[](std::size_t n)
        {
            return n < size ? string[n] : 0;
        }

        constexpr std::size_t get_size()
        {
            return size;
        }

        constexpr const char* get_string()
        {
            return string;
        }

        //This method is related with Fowler–Noll–Vo hash function
        constexpr unsigned hash(int n=0, unsigned h=2166136261)
        {
            return n == size ? h : hash(n+1,(h * 16777619) ^ (string[n]));
        }

    private:
        const char* string;
        std::size_t size;
};

// output function that requires a compile-time constant, for testing
template<int N> struct OUT
{
    OUT() { std::cout << N << '\n'; }
};

int constexpr operator "" _const(const char* str, size_t sz)
{
    return conststr(str,sz).hash();
}

int main()
{
    OUT<"A dummy string"_const> out;
    OUT<"A very long template parameter as a const char*"_const> out2;
}

在此示例代码中,out的类型为OUT<1494474505>,并且out2的类型为OUT<106227495>。该代码背后的魔力是conststr::hash(),它是使用FNV Hash functionconstexpr递归。因此,它为const char *创建了一个完整的哈希,希望它是一个唯一的哈希。

我对此方法有一些疑问:
  • 这是一种安全的使用方法吗?还是这种方法在特定用途上是邪恶的?
  • 是否可以编写一个更好的哈希函数,为每个字符串创建不同的整数,而又不限制为多个字符? (在我的方法中,长度足够长)
  • 您能编写一个通过const char*隐式将int constexpr转换为conststr的代码,这样我们就不需要美观(也费时)的_const用户定义的字符串文字了吗?例如,OUT<"String">将是合法的(并将“String”转换为整数)。

  • 任何帮助将不胜感激,非常感谢。

    最佳答案

    尽管您的方法非常有趣,但这实际上不是将字符串文字作为模板参数传递的方法。实际上,它是基于字符串文字的模板参数生成器,这是不一样的:您无法从string中检索hashed_string ...这有点破坏了字符串文字在模板中的全部兴趣。
    编辑:当使用的哈希是字母的加权总和时,以下是正确的,在OP编辑后不是这种情况。

    据我所知,您不能在当前标准中直接在模板参数中传递字符串文字。但是,您可以“伪造”它。这是我通常使用的:

    struct string_holder              //
    {                                 // All of this can be heavily optimized by
        static const char* asString() // the compiler. It is also easy to generate
        {                             // with a macro.
            return "Hello world!";    //
        }                             //
    };                                //
    
    然后,我通过类型参数传递“假字符串文字”:
    template<typename str>
    struct out
    {
        out()
        {
            std::cout << str::asString() << "\n";
        }
    };
    
    EDIT2 :您在注释中说过,您用它来区分类模板的几种特殊化。您显示的方法对此有效,但您也可以使用标签:
    // tags
    struct myTag {};
    struct Long {};
    struct Float {};
    
    // class template
    template<typename tag>
    struct Integer
    {
        // ...
    };
    template<> struct Integer<Long> { /* ... */ };
    
    // use
    Integer<Long> ...;  // those are 2
    Integer<Float> ...; // different types
    

    关于c++ - 使用 “constexpr”将字符串文字用作模板参数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15861669/

    10-09 06:46
    查看更多