【问题标题】:Lexicographically compare two strings at compile time in C++11在 C++11 的编译时按字典顺序比较两个字符串
【发布时间】:2017-02-22 06:15:38
【问题描述】:

我正在尝试使用受 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)
{
}

【问题讨论】:

    标签: c++ c++11 constexpr


    【解决方案1】:
    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());
    }
    

    【讨论】:

      【解决方案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;
      }
      

      注意,我用0 替换了你的throw,因为你抛出的不是常量表达式。

      【讨论】:

      • 感谢您的回答,但我认为该 throw 语句没有任何问题,因为如果在 constexpr 上下文中调用它将无法编译。
      • 你是绝对正确的。 stackoverflow.com/questions/34280729/…
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-25
      • 2013-12-16
      • 2015-03-31
      • 2022-01-02
      相关资源
      最近更新 更多