如何将字符串转换为常量整数?

时间:2016-11-21 04:57:00

标签: c++ c++11

我有代表图像名称的字符串,如" foobar.png"等等 如您所知,C ++中的switch-case不支持切换字符串。

我试图通过将字符串散列到std :: size_t,然后在switch-case语句中使用该值来解决此问题。

例如:

        //frameName is an std::string which represents foobar.png etc..
        switch (shs(frameName)) { //shs is my hash func which returns std::size_t;
            case shs(Pfn::fs1x1): //Problem in this line
            default:{
                break;
            }
        }

在单独的文件(Pfn.hpp)中:

命名空间Pfn {     const std :: string fs1x1 =" fs1x1&#34 ;; };

问题是,在我的case语句中,编译器报告shs(Pfn::fs1x1)不是常量表达式。确切的错误消息是:

  

案例值不是常量表达式:

事先计算出所有哈希值然后将它们硬编码到case语句中真的很乏味。你有什么建议我怎么能在运行时以某种方式创建常量表达式?

编辑:我的功能:

static std::size_t shs(std::string string){
    return Hash::shs::hs(string);
}

// ...

namespace Hash{
    struct shs{
    public:
        inline std::size_t operator()(const std::string &string)const{
            return hashString(string);
        }

        static std::size_t hs(const std::string &string){
            std::size_t seed = 0;
            hash_combine(seed,string);
            return seed;
        }

        //From Boost::hash_combine.
        template <class T>
        static inline void hash_combine(std::size_t& seed, const T& v)
        {
            std::hash<T> hasher;
            seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
        };
    };
}

3 个答案:

答案 0 :(得分:3)

shs的论点必须是constexpr,而shs本身也必须是constexpr。有可能,由于对constexpr函数的C ++ 11约束,您可能希望为编译时版本和哈希的运行时版本提供不同的实现。

wrote前一段时间关于这个主题的帖子,使用fnv1a作为哈希算法。以下是重要部分:

常量:

typedef std::uint64_t hash_t;

constexpr hash_t prime = 0x100000001B3ull;
constexpr hash_t basis = 0xCBF29CE484222325ull;

运行时哈希:

hash_t hash(char const* str)
{
    hash_t ret{basis};

    while(*str){
        ret ^= *str;
        ret *= prime;
        str++;
    }

    return ret;
}

编译时哈希:

constexpr hash_t hash_compile_time(char const* str, hash_t last_value = basis)
{
    return *str ? hash_compile_time(str+1, (*str ^ last_value) * prime) : last_value;
}

用户定义的字符串文字:

constexpr unsigned long long operator "" _hash(char const* p, size_t)
{
    return hash_compile_time(p);
}

和用法:

switch(fnv1a_64::hash(str)){
case "first"_hash:
    cout << "1st one" << endl;
    break;
case "second"_hash:
    cout << "2nd one" << endl;
    break;
case "third"_hash:
    cout << "3rd one" << endl;
    break;
default:
    cout << "Default..." << endl;
}

demo

但是,请想想孩子们!除非你能保证不存在哈希冲突,否则这就是玩火,不适合作为生产代码。

答案 1 :(得分:2)

我假设你的哈希不会因为这个答案而发生任何冲突。

如果您将哈希定义为预处理器函数,则可以创建可以匹配的常量。

这篇文章可能有所帮助:Compile-time (preprocessor) hashing of string

答案 2 :(得分:1)

根据定义,常量表达式表示可以在编译时计算的表达式。

但如果case func():constexpr,则可以使用func()