Natürlich können wir zwei Zeichenfolgenliterale in einer constexpr
Funktion verketten, aber was ist mit der Verkettung eines Zeichenfolgenliterals mit einer Zeichenfolge, die von einer anderen constexpr
Funktion wie im folgenden Code zurückgegeben wird?
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>);
Der Code macht eine compilerunabhängige Zeichenfolgenkennung von einem arithmetischen Typ.
EDIT1:
Ein etwas komplizierteres Beispiel ist:
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
(und wahrscheinlich + verschiedene Vorlagen)typeid
Bediener erzielt . Ein Teil des Grundestypeid
ist ein Teil der Sprache (z. B. unterstützt durch ein dediziertes Sprachschlüsselwort) und keine Bibliotheksfunktion. Die Implementierung basiert auf "Compilermagie". Eine Implementierung in der Sprache ist ohne eine spezielle Unterstützung durch die Implementierung nicht möglich .Antworten:
Hier ist eine schnelle Zeichenfolgeklasse für die Kompilierungszeit:
Sie können es so verwenden:
was zu Aussagen führt wie:
Vorbeigehen.
Live Beispiel .
Eine ärgerliche Sache ist nun, dass die Länge des Puffers im Typsystem liegt. Sie können ein
length
Feld hinzufügen undN
"Puffergröße" festlegen und so ändernct_str
, dass nur bis zulength
den nachfolgenden Bytes kopiert wird und diese beibehalten werden0
. Überschreiben Sie danncommon_type
, um das MaximumN
beider Seiten zurückzugeben.Das würde erlauben Sie passieren
ct_str{"uint"}
undct_str{"int"}
in der gleichen Art von Wert und macht den Implementierungscode ein bisschen weniger ärgerlich.Die Funktionsimplementierungen werden nun:
Das ist viel natürlicher zu schreiben.
Live Beispiel .
quelle
else
inget_arithmetic_size
mit ,if constexpr
auch wenn Sie tunreturn
, denn ohneelse
die Behauptungdependent_false_v<T>
fehl.Nein, das ist unmöglich. Sie können Folgendes implementieren (es ist C ++ 14).
https://ideone.com/BaADaM
Wenn Sie nicht gerne verwenden
<cmath>
, können Sie Folgendes ersetzenstd::log
:quelle
std::log
ist zu kompliziert für mich, brauche eine generische Technik, um Strings zu verkettenconstexpr
, keine Sorge überstd::log()
. Sie können es ersetzen, aber der Code wird vergrößert,std::log
nochstd::strcmp
garantiertconstexpr
. Tatsächlich verbietet der Standard ausdrücklich, dass sieconstexpr
seit C ++ 14 sind. Daher verwendet Ihr Code tatsächlich nicht standardmäßige Erweiterungen.