template<typename T, std::size_t N>
constexpr std::size_t countof(T const(&)[N]) { return N; }
besteht beide Ihre Tests. Es gibt keine Möglichkeit, eine int*
in eine T const(&)[N]
umzuwandeln, so dass kein Sperrcode benötigt wird.
es zu verlängern, wir sollten hinzufügen:
template<typename T, std::size_t N>
constexpr std::size_t countof(std::array<T,N> const&) { return N; }
ich sogar versucht sein könnte, um sie zu erweitern size()
für Behälter zu rufen. Während es normalerweise keine Kompilierzeit ist, könnte die Einheitlichkeit nützlich sein:
for(int i=0; i<countof(c); ++i) {
// code
}
oder was haben Sie.
template<typename T, std::size_t N>
constexpr std::size_t countof(T const(&)[N]) { return N; }
template<typename T> struct type_sink { typedef void type; };
template<typename T> using TypeSink = typename type_sink<T>::type;
template<typename T, typename=void>
struct has_size : std::false_type {};
template<typename T>
struct has_size<T, TypeSink< decltype(std::declval<T>().size()) > >:
std::true_type
{};
template<bool b, typename T=void>
using EnableIf = typename std::enable_if<b,T>::type;
template<typename T>
constexpr
EnableIf<has_size<T const&>::value,std::size_t>
countof(T const& t) {
return t.size();
}
// This is optional. It returns `void`, because there
// is no need to pretend it returns `std::size_t`:
template<typename T>
constexpr
EnableIf<std::is_pointer<T>::value>
countof(T const& t) = delete;
die ziemlich ausführlich ist, sondern gibt uns std::array
Unterstützung, std::initializer_list
Unterstützung, C-Stil-Array-Unterstützung - alle bei der Kompilierung - und zur Laufzeit Standardcontainer und Strings sind alle countof
können. Wenn Sie einen Zeiger übergeben, wird Ihnen mitgeteilt, dass die von Ihnen aufgerufene Funktion delete
ed ist.
Ich versuchte in diesem Fall eine static_assert
zu erstellen, aber es kam zu Problemen mit der Auflösungsregel, dass jede template
eine gültige Spezialisierung haben muss. Ich vermute, das Routing des gesamten Problems in eine countof_impl
Klasse mit SFINAE-basierten Spezialisierungen könnte dieses Problem beheben.
Ein Nachteil der =delete
oder static_assert
Lösung ist, dass eine Überladung tatsächlich für Zeiger existiert. Wenn Sie das nicht haben, dann gibt es einfach keine gültige Funktion zum Aufrufen, die einen Zeiger braucht: das ist näher an der Wahrheit.
Warum sollte es kompilieren? 'typenname std :: enable_if :: value> :: type' wird falsch sein, weil' int' nicht für 'is_array' gilt. –
@remyabel: Doh! Natürlich hast du recht. – KnowItAllWannabe