在C ++ 11中,在编译时按字典顺序比较两个字符串

时间:2017-02-22 06:15:38

标签: c++ c++11 constexpr

我尝试使用https://stackoverflow.com/a/15863826/2859099启发的str_const课程

#include <cstddef>
#include <stdexcept>

class str_const
{
public:
    template<std::size_t N>
    constexpr str_const(const char(&arr)[N]) noexcept : str{arr}, len{N - 1} 
    {
    }

    constexpr char operator[](std::size_t i) const 
    {
        return i < len ? str[i] : throw std::out_of_range{""}; 
    }

    constexpr std::size_t size() const noexcept { return len; }

    constexpr operator const char*() const noexcept { return str; } 

    constexpr const char* c_str() const noexcept { return str; }

private:
    const char* const str;
    const std::size_t len;
};

考虑到C ++ 11中对constexpr函数的限制,如何实现以下词典比较:

constexpr bool operator<(str_const lhs, str_const rhs)
{
}

2 个答案:

答案 0 :(得分:3)

constexpr bool less_impl(const char* s1, std::size_t n1, const char* s2, std::size_t n2)
{
    return n2 == 0    ? false :
           n1 == 0    ? true :
           *s1 == *s2 ? less_impl(s1 + 1, n1 - 1, s2 + 1, n2 - 1) :
                        *s1 < *s2;
}

constexpr bool operator<(str_const lhs, str_const rhs)
{
    return less_impl(lhs.c_str(), lhs.size(), rhs.c_str(), rhs.size());
}

答案 1 :(得分:2)

通常你会写一个循环。在这里,您需要用尾递归替换它。这是我得到的:

#include <iostream>
#include <type_traits>
#include <cstddef>

class str_const
{
public:
    template<std::size_t N>
    constexpr str_const(const char(&arr)[N]) noexcept : str{arr}, len{N - 1}
    {
    }

    constexpr char operator[](std::size_t i) const
    {
        return i < len ? str[i] : throw std::out_of_range{""}; 
    }

    constexpr std::size_t size() const noexcept { return len; }

    constexpr operator const char*() const noexcept { return str; }

    constexpr const char* c_str() const noexcept { return str; }

private:
    const char* const str;
    const std::size_t len;
};

namespace detail {
constexpr bool cmp(str_const lhs, str_const rhs, std::size_t idx) {
return lhs.size()<=idx ? true :
       rhs.size()<=idx ? false :
       lhs[idx]<rhs[idx] ? true :
       rhs[idx]<lhs[idx] ? false :
       cmp(lhs,rhs,idx+1);
}
}

constexpr bool operator<(str_const lhs, str_const rhs) {
return detail::cmp(lhs,rhs,0);
}

int main() {
std::cout << std::integral_constant< bool, str_const("def")<str_const("abc") >::value << std::endl;
std::cout << std::integral_constant< bool, str_const("abc")<str_const("abc") >::value << std::endl;
}

注意,我已将throw替换为0,因为您投掷的内容不是常量