为什么被认为是编译时的文字不知道?

问题描述 投票:0回答:1

您好,我有一个非常具体的问题,我已经尝试解决这个问题几个小时了。

我有一个关键类,能够将字符串存储为模板参数。我想用它来使用

key_index<KEY_TYPE>::get_index()
有效地从此类键获取索引。但是,我在从字符串创建键时遇到了问题。尽管事实上
str
参数在编译时是已知的,但编译器只是不想让我将它用作模板参数。

有人知道解决方法吗?或者这完全是胡说八道,我应该把它扔到大海里并使用 std::unordered_map 代替?

PS:我正在 Visual Studio 中使用 MSVC++,尚未在其他编译器中尝试过,但老实说,我认为它的行为不会有所不同。

#include <iostream>
#include <type_traits>
#include <array>
#include <memory>
#include <stdio.h>

// An array of characters with a fixed size
template <std::size_t N>
using str_ct = std::array<char, N>;

// A key type that holds a string literal
template <char... Chars>
struct key {
    using _is_key = void;
    static constexpr str_ct<sizeof...(Chars) + 1> value = { Chars..., '\0' };
};

// A concept to check if a type is a key
template <class T>
concept key_concept = requires {
    typename T::_is_key;
};

// Global index for keys
struct key_index_base {
protected:
    static std::size_t index;
};

std::size_t key_index_base::index = 0;

// A type that holds the index of a key
template <key_concept KEY>
struct key_index : public key_index_base {
    static std::size_t get_index() {
        static std::size_t index = key_index_base::index++;
        return index;
    }
};

// Specialization for non-empty string literals
template <size_t N, size_t I, char... Chars>
struct string_to_key_helper {
    static consteval auto convert(const char(&str)[N]) {
        if constexpr (I < N - 1) // -1 to exclude the null terminator
            return string_to_key_helper<N, I + 1, Chars..., str[I]>::convert(str);
        else
            return key<Chars...>{};
    }
};

// Helper function to deduce the array size and start the conversion
template <std::size_t N>
constexpr auto make_key(const char(&str)[N]) {
    return string_to_key_helper<N, 0>::convert(str);
}

int main() {
    constexpr auto k = make_key("Hello, World!");
    
    for (auto c : k.value) {
        std::cout << (int)c << " ";
    }
}
c++ c++20 metaprogramming variadic-templates
1个回答
0
投票

Consteval 函数参数不是函数内的常量表达式:https://stackoverflow.com/a/56131418/5754656

函数参数的值从来都不是常量表达式,因此您会在

str[I]
中得到
string_to_key_helper<N, I + 1, Chars..., str[I]>
的错误。

你可以让

key<"string literal">
工作:

https://godbolt.org/z/vjKWoca17

template <std::size_t N>
struct CString {
    consteval CString(const char(& s)[N]) {
        for (std::size_t i = 0; i < N; ++i) {
            value[i] = s[i];
        }
        if (s[N - 1u]) {
            throw "CString must be NUL-terminated like a string literal";
        }
    }

    char value[N];
    constexpr operator std::string_view() const noexcept {
        return { value, value + N - 1u };
    }
};

template <CString S>
struct key {
    using _is_key = void;
    static constexpr const char(& value)[std::size(S.value)] = S.value;
};

int main() {
    constexpr auto k = key<"Hello, world!">();

    for (char c : k.value) {
        std::cout << int{c} << ' ';
    }
    std::cout << '\n';
}
© www.soinside.com 2019 - 2024. All rights reserved.