2

私は、一般的なものとコンテナ型のどちらかを選択する必要があるコード ブロックでデータ型を選択する際に、より衒学的になることを考えていました。私の問題は、次のコード ブロックがある場合、その方法がわからないことです。誰か助けてくれませんか?size_type size_tcontainer::size_type

template<typename some_container>
int func(some_container& input)
{
    //Some code...
    //...
    decltype(input.size()) variable_x; //Choose this if defined,
    size_t                 variable_x; //otherwise choose this
    //... Some more code...
}

この場合some_containerカスタム コンテナーである可能性があり、機能を提供しませんsize()size_tこの考えに至ったのは、 and container::size_typeat size_t と container::size_typeの違いを読んだことでした。コンパイル時に型が STL コンテナーかどうかを判断するも読みましたが、このアプローチは私の状況では少し面倒に感じます。

4

5 に答える 5

5

を使用するのは正しい方法ですdecltype。秘訣は、テンプレート クラスまたは関数のオーバーロードを使用して簡単に実行できる SFINAE を使用することです。C++11 ではとても簡単なので、関数の方法を示します。

// One helper per size_type source
template <typename T>
auto size_type_alt(T const& t) -> decltype(t.size());

auto size_type_alt(...) -> std::size_t;

// The switch between helpers
template <typename T>
auto size_type_switch() -> decltype(size_type_alt(std::declval<T>{}));

// And syntactic sugar
template <typename T>
using size_type = decltype(size_type_switch<T>());

使用法:

template <typename T>
void some_algorithm(T const& t) {
    size_type<T> const size = 0;
    // ...
}

注: スイッチと糖衣層を一緒にブレンドすることもできますが、手順を個別に見ていただければ幸いです。

于 2012-10-21T13:00:20.797 に答える
4

class以下は、 に型 ( などsize_type)が含まれているかどうかを判断する 1 つの方法です。

template <typename T> 
struct Has_size_type
{
  typedef char (&yes)[2];

  template <typename C> static yes test(typename C::size_type*);
  template <typename> static char test(...);

  static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};

そして、次の2つのタイプから選択する方法は次のとおりです。

template<bool> struct Bool;
template<typename T, typename = Bool<true> >
struct Set { typedef size_type type; };
template<typename T>
struct Set<T,Bool<Has_size_type<T>::value> > { typedef typename T::size_type type; };

Edit start : 別の簡単な方法を次に示します。

template<typename T>
struct void_ { typedef void type; };

template<typename T, typename = void>
struct Set 
{ typedef size_type type; };

template<typename T>
struct Set<T,typename void_<typename T::size_type>::type>
{ typedef typename T::size_type type; };

編集終了

最後に、以下のように使用します。

template<typename some_container>
int func(some_container& input)
{
  typedef typename Set<some_container>::type type;
}

したがって、現在typesize_typeまたはsome_container::size_typeのいずれかです。

于 2012-10-21T12:31:47.830 に答える
2

がない場合size_type、コンテナではありません。限目。

標準では、すべてのコンテナが という名前の型を定義する必要がありますsize_type。N3337 から、23.2.1 一般的なコンテナー要件 [container.requirements.general]:

式: X::size_type
戻り値の型:符号なし整数型
アサーション: size_type負でない任意の値を表すことができます difference_type
複雑さ:コンパイル時

したがって、コードは次のように単純になります。

typename some_container::size_type variable_x;
于 2012-10-21T12:15:23.050 に答える
0

typename some_container::size_typeこれには、ほとんどのSTLコンパイラのtypedefsize_typeを使用できますsize_tが、この手法を使用すると、カスタムコンテナをサポートできます。

于 2012-10-21T12:03:07.190 に答える
0

@ Matthieu M.の回答を出発点として使用して、SFINAE を使用して、チェックするのではなく、 T::size_type が存在するかどうかを判断しsize()ます。非常に似ていますが、次を避けるだけautoです:

/** Fails if T::size_type isn't defined. */ 
template <class T>
typename T::size_type SizeType(const T &&t);

/** Fallback to a known size. */
template <class T>
std::size_t SizeType(const T &t);

...

using size_type = decltype(SizeType<T>(std::declval<T>()));

Matthieu が行ったように、あいまいさを避けるために、この場合、メソッドへのパラメーターは異なる必要があります。

于 2014-05-29T14:11:56.773 に答える