template<typename T, std::size_t N>
constexpr std::size_t countof( T const(&)[N] ) { return N; }
両方のテストに合格します。を に変換する方法がないint*
ためT const(&)[N]
、無効にするコードは必要ありません。
それを拡張するには、次を追加する必要があります。
template<typename T, std::size_t N>
constexpr std::size_t countof( std::array<T,N> const& ) { return N; }
size()
コンテナの呼び出しに拡張したくなるかもしれません。通常はコンパイル時ではありませんが、統一性が役立つ場合があります。
for(int i=0; i<countof(c); ++i) {
// code
}
またはあなたは何を持っていますか。
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;
これは非常に冗長ですが、std::array
サポート、std::initializer_list
サポート、C スタイルの配列サポート (すべてコンパイル時) を提供し、実行時には標準のコンテナーと文字列をすべて使用countof
できます。ポインターを渡すと、呼び出した関数がdelete
ed であることが通知されます。
その場合にを作成しようとしましたが、有効な特殊化が必要static_assert
であるという解決ルールで問題が発生しました。template
問題全体countof_impl
を SFINAE ベースの特殊化を持つクラスにルーティングすると、その問題が解決するのではないかと思います。
=delete
orソリューションの欠点は、static_assert
実際にはポインターのオーバーロードが存在することです。それがない場合は、ポインターを受け取る有効な関数を呼び出すことはできません。これは真実に近いです。