2017-02-22 8 views
2

私はC++ 11でconstexprの機能上の制限を考慮すると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; 
}; 

からインスピレーションを得たstr_constクラスを使用しようとしている、どのように実装するには、コンパイル時に2つの文字列を比較します以下の辞書式の比較:

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

注、私は0であなたのthrowを置き換えます。

+0

答えが分かりますが、const文のコンテキストで呼び出された場合にコンパイルが失敗するだけなので、このthrow文には何の問題もありません。 –

+0

あなたは絶対に正しいです。 http://stackoverflow.com/questions/34280729/throw-in-constexpr-function – CygnusX1