Đây là một lớp chuỗi thời gian biên dịch nhanh:
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>;
bạn có thể sử dụng nó như thế này:
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>();
}
dẫn đến các tuyên bố như:
static_assert(make_type_name<int>() == make_type_name<int32_t>());
đi qua.
Ví dụ sống .
Bây giờ một điều khó chịu là chiều dài của bộ đệm nằm trong hệ thống loại. Bạn có thể thêm một lengthtrường và tạo N"kích thước bộ đệm" và sửa đổi ct_strđể chỉ sao chép tối đa lengthvà để lại các byte theo sau 0. Sau đó ghi đè common_typeđể trả lại tối đa Ncủa cả hai bên.
Điều đó sẽ cho phép bạn vượt qua ct_str{"uint"}và ct_str{"int"}trong cùng loại giá trị và làm cho mã triển khai bớt khó chịu hơn một chút.
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>;
Việc triển khai chức năng bây giờ trở thành:
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>();
}
đó là rất nhiều tự nhiên để viết.
Ví dụ sống .