Jelas kita dapat menggabungkan dua string literal dalam suatu constexpr
fungsi, tetapi bagaimana dengan concatenation string string dengan string yang dikembalikan oleh constexpr
fungsi lain seperti pada kode di bawah ini?
template <class T>
constexpr const char * 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";
default: static_assert(dependent_false_v<T>);
}
}
template <class T>
constexpr std::enable_if_t<std::is_arithmetic_v<T>, const char *> make_type_name()
{
const char * prefix = std::is_signed_v<T> ? "int" : "uint";
return prefix; // how to concatenate prefix with get_arithmetic_size<T>() ?
}
static_assert(strings_equal(make_type_name<int>, make_type_name<int32_t>);
Kode ini membuat pengidentifikasi string kompiler-independen dari tipe aritmatika.
EDIT1:
Contoh yang sedikit lebih rumit adalah:
template<typename Test, template<typename...> class Ref>
struct is_specialization : std::false_type {};
template<template<typename...> class Ref, typename... Args>
struct is_specialization<Ref<Args...>, Ref> : std::true_type {};
template <class T>
constexpr std::enable_if_t<is_specialization<T, std::vector>::value || is_specialization<T, std::list>::value, const char *> make_type_name()
{
return "sequence"; // + make_type_name<typename T::value_type>;
}
static_assert(strings_equal(make_type_name<std::vector<int>>(), make_type_name<std::list<int>>()));
std::array
(dan mungkin + templat variadic)typeid
operator. Sebagian alasannyatypeid
adalah bagian dari bahasa (misalnya didukung oleh kata kunci bahasa khusus) daripada fungsi perpustakaan adalah bahwa mengimplementasikannya bergantung pada "sihir kompiler" - tidak mungkin untuk mengimplementasikannya dalam bahasa tanpa dukungan khusus dari implementasi .Jawaban:
Berikut ini adalah kelas string waktu kompilasi cepat:
Anda dapat menggunakannya seperti ini:
yang mengarah pada pernyataan seperti:
lewat.
Contoh langsung .
Sekarang satu hal yang mengganggu adalah bahwa panjang buffer ada di sistem tipe. Anda bisa menambahkan
length
bidang, dan menjadikannyaN
"ukuran buffer", dan memodifikasict_str
hanya menyalin hinggalength
meninggalkan trailing byte0
. Kemudian ganticommon_type
untuk mengembalikan maksN
kedua sisi.Itu akan memungkinkan Anda untuk lulus
ct_str{"uint"}
danct_str{"int"}
dalam jenis nilai yang sama dan membuat kode implementasi sedikit kurang mengganggu.Implementasi fungsi sekarang menjadi:
yang jauh lebih alami untuk ditulis.
Contoh langsung .
sumber
else
diget_arithmetic_size
denganif constexpr
bahkan jika Andareturn
, karena tanpaelse
pernyataandependent_false_v<T>
akan gagal.Tidak, itu tidak mungkin. Anda dapat mengimplementasikan sesuatu seperti di bawah ini (ini C ++ 14).
https://ideone.com/BaADaM
Jika Anda tidak suka menggunakan
<cmath>
, Anda dapat menggantistd::log
:sumber
std::log
terlalu rumit bagi saya, perlu beberapa teknik generik untuk menyatukan stringconstexpr
, jangan khawatirstd::log()
. Anda dapat menggantinya, tetapi kode akan diperbesar,std::log
juga tidakstd::strcmp
dijamin akanconstexpr
. Bahkan, standar khusus melarang merekaconstexpr
sejak C ++ 14. Karenanya, kode Anda sebenarnya menggunakan ekstensi non-standar.