यहाँ एक त्वरित संकलन समय स्ट्रिंग क्लास है:
template<std::size_t N>
struct ct_str
{
char state[N+1] = {0};
constexpr ct_str( char const(&arr)[N+1] )
{
for (std::size_t i = 0; i < N; ++i)
state[i] = arr[i];
}
constexpr char operator[](std::size_t i) const { return state[i]; }
constexpr char& operator[](std::size_t i) { return state[i]; }
constexpr explicit operator char const*() const { return state; }
constexpr char const* data() const { return state; }
constexpr std::size_t size() const { return N; }
constexpr char const* begin() const { return state; }
constexpr char const* end() const { return begin()+size(); }
constexpr ct_str() = default;
constexpr ct_str( ct_str const& ) = default;
constexpr ct_str& operator=( ct_str const& ) = default;
template<std::size_t M>
friend constexpr ct_str<N+M> operator+( ct_str lhs, ct_str<M> rhs )
{
ct_str<N+M> retval;
for (std::size_t i = 0; i < N; ++i)
retval[i] = lhs[i];
for (std::size_t i = 0; i < M; ++i)
retval[N+i] = rhs[i];
return retval;
}
friend constexpr bool operator==( ct_str lhs, ct_str rhs )
{
for (std::size_t i = 0; i < N; ++i)
if (lhs[i] != rhs[i]) return false;
return true;
}
friend constexpr bool operator!=( ct_str lhs, ct_str rhs )
{
for (std::size_t i = 0; i < N; ++i)
if (lhs[i] != rhs[i]) return true;
return false;
}
template<std::size_t M, std::enable_if_t< M!=N, bool > = true>
friend constexpr bool operator!=( ct_str lhs, ct_str<M> rhs ) { return true; }
template<std::size_t M, std::enable_if_t< M!=N, bool > = true>
friend bool operator==( ct_str, ct_str<M> ) { return false; }
};
template<std::size_t N>
ct_str( char const(&)[N] )->ct_str<N-1>;
आप इसे इस तरह से उपयोग कर सकते हैं:
template <class T>
constexpr auto get_arithmetic_size()
{
if constexpr (sizeof(T)==1)
return ct_str{"1"};
if constexpr (sizeof(T)==2)
return ct_str{"2"};
if constexpr (sizeof(T)==4)
return ct_str{"4"};
if constexpr (sizeof(T)==8)
return ct_str{"8"};
if constexpr (sizeof(T)==16)
return ct_str{"16"};
}
template <class T, std::enable_if_t<std::is_arithmetic<T>{}, bool> = true>
constexpr auto make_type_name()
{
if constexpr (std::is_signed<T>{})
return ct_str{"int"} + get_arithmetic_size<T>();
else
return ct_str{"uint"} + get_arithmetic_size<T>();
}
जो इस तरह के बयान की ओर जाता है:
static_assert(make_type_name<int>() == make_type_name<int32_t>());
गुजर।
जीवंत उदाहरण ।
अब एक कष्टप्रद बात यह है कि बफर की लंबाई प्रकार प्रणाली में है। आप एक length
फ़ील्ड जोड़ सकते हैं , और N
"बफर आकार" बना सकते हैं, और ct_str
केवल length
अनुलिपि बाइट्स को कॉपी और छोड़ सकते हैं 0
। फिर दोनों पक्षों common_type
की अधिकतम वापसी के लिए ओवरराइड करें N
।
यह अनुमति देगा कि आप पास ct_str{"uint"}
और ct_str{"int"}
उसी प्रकार के मूल्य में करें और कार्यान्वयन कोड को थोड़ा कम कष्टप्रद बना दें।
template<std::size_t N>
struct ct_str
{
char state[N+1] = {0};
template<std::size_t M, std::enable_if_t< (M<=N+1), bool > = true>
constexpr ct_str( char const(&arr)[M] ):
ct_str( arr, std::make_index_sequence<M>{} )
{}
template<std::size_t M, std::enable_if_t< (M<N), bool > = true >
constexpr ct_str( ct_str<M> const& o ):
ct_str( o, std::make_index_sequence<M>{} )
{}
private:
template<std::size_t M, std::size_t...Is>
constexpr ct_str( char const(&arr)[M], std::index_sequence<Is...> ):
state{ arr[Is]... }
{}
template<std::size_t M, std::size_t...Is>
constexpr ct_str( ct_str<M> const& o, std::index_sequence<Is...> ):
state{ o[Is]... }
{}
public:
constexpr char operator[](std::size_t i) const { return state[i]; }
constexpr char& operator[](std::size_t i) { return state[i]; }
constexpr explicit operator char const*() const { return state; }
constexpr char const* data() const { return state; }
constexpr std::size_t size() const {
std::size_t retval = 0;
while(state[retval]) {
++retval;
}
return retval;
}
constexpr char const* begin() const { return state; }
constexpr char const* end() const { return begin()+size(); }
constexpr ct_str() = default;
constexpr ct_str( ct_str const& ) = default;
constexpr ct_str& operator=( ct_str const& ) = default;
template<std::size_t M>
friend constexpr ct_str<N+M> operator+( ct_str lhs, ct_str<M> rhs )
{
ct_str<N+M> retval;
for (std::size_t i = 0; i < lhs.size(); ++i)
retval[i] = lhs[i];
for (std::size_t i = 0; i < rhs.size(); ++i)
retval[lhs.size()+i] = rhs[i];
return retval;
}
template<std::size_t M>
friend constexpr bool operator==( ct_str lhs, ct_str<M> rhs )
{
if (lhs.size() != rhs.size()) return false;
for (std::size_t i = 0; i < lhs.size(); ++i)
if (lhs[i] != rhs[i]) return false;
return true;
}
template<std::size_t M>
friend constexpr bool operator!=( ct_str lhs, ct_str<M> rhs )
{
if (lhs.size() != rhs.size()) return true;
for (std::size_t i = 0; i < lhs.size(); ++i)
if (lhs[i] != rhs[i]) return true;
return false;
}
};
template<std::size_t N>
ct_str( char const(&)[N] )->ct_str<N-1>;
अब फ़ंक्शन कार्यान्वयन बन जाते हैं:
template <class T>
constexpr ct_str<2> get_arithmetic_size()
{
switch (sizeof(T)) {
case 1: return "1";
case 2: return "2";
case 4: return "4";
case 8: return "8";
case 16: return "16";
}
}
template <class T, std::enable_if_t<std::is_arithmetic<T>{}, bool> = true>
constexpr auto make_type_name()
{
constexpr auto base = std::is_signed<T>{}?ct_str{"int"}:ct_str{"uint"};
return base + get_arithmetic_size<T>();
}
जो है एक बहुत अधिक लिखने के लिए प्राकृतिक।
जीवंत उदाहरण ।