Reputation: 327
I'm trying to use the str_const
class inspired from https://stackoverflow.com/a/15863826/2859099
#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;
};
Considering the restrictions on constexpr functions in C++11, how to implement the following lexicographical comparison:
constexpr bool operator<(str_const lhs, str_const rhs)
{
}
Upvotes: 2
Views: 663
Reputation: 21808
Typically you would write a loop. Here you need to replace it with a tail recursion. Here is what I have got:
#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;
}
Note, I replaced your .throw
with 0
because what you are throwing is not a constant expression
Upvotes: 2
Reputation: 137425
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());
}
Upvotes: 3