2017-02-22 3 views
2

Я пытаюсь использовать str_const класс вдохновленный от https://stackoverflow.com/a/15863826/2859099Лексикографически сравнить две строки во время компиляции в C++ 11

#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; 
}; 

Учитывая ограничения на функции constexpr в C++ 11, как реализовать следующее лексикографическое сравнение:

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

ответ

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()); 
} 
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, потому что вы бросаете не является постоянным выражением.

+0

Оцените свой ответ, но я не вижу никаких проблем с этим оператором throw, потому что он просто не скомпилируется, если вызван в контексте constexpr. –

+0

Вы абсолютно правы. http://stackoverflow.com/questions/34280729/throw-in-constexpr-function – CygnusX1

Смежные вопросы