考察・まとめ
問題
- SFINAEは何の略か。
- SFINAEとはどのような仕組みのことを言うか。
- 型特性を英語で言え。
- 型特性メタ関数とは何か。
- 型Tがiterator型を持っているか判定するhas_iteratorを様々な方法で実装せよ。
解答
- Substitution Failure Is Not An Error
- テンプレートをインスタンス化する際に置き換えに失敗したら、コンパイルエラーとせずに、その関数をオーバーロードの対象から外す仕組み。
- type traits
- 型特性メタ関数とは、型の特徴(整数型、ポインタ型、参照型、クラス、継承関係など)を判定したり型の特徴を操作したりするためのメタ関数。
#include <bits/stdc++.h>
template<class T>
class has_iterator {
typedef char yes;
typedef struct { char a[2]; } no;
template <class U> static yes test(typename U::iterator*);
template <class U> static no test(...);
public:
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
template <class T>
constexpr bool has_iterator_constexpr_func_impl(typename T::iterator*)
{
return true;
}
template <class T>
constexpr bool has_iterator_constexpr_func_impl(...)
{
return false;
}
template <class T>
constexpr bool has_iterator_constexpr_func()
{
return has_iterator_constexpr_func_impl<T>(nullptr);
}
template <class T>
class has_iterator_constexpr {
template <class U> static constexpr bool check(typename U::iterator*) { return true; }
template <class U> static constexpr bool check(...) { return false; }
public:
static constexpr bool value = check<T>(nullptr);
};
struct has_iterator_impl_decltype {
template <class T> static std::true_type check(typename T::iterator*);
template <class T> static std::false_type check(...);
};
template <class T>
class has_iterator_decltype
: public decltype(has_iterator_impl_decltype::check<T>(nullptr)) {};
int main() {
static_assert(has_iterator<std::vector<int>>::value, "vector has iterator");
static_assert(!has_iterator<int>::value, "int doesn't have iterator");
static_assert(has_iterator_constexpr_func<std::vector<int>>(), "vector has iterator");
static_assert(!has_iterator_constexpr_func<int>(), "int doesn't have iterator");
static_assert(has_iterator_constexpr<std::vector<int>>::value, "vector has iterator");
static_assert(!has_iterator_constexpr<int>::value, "int doesn't have iterator");
static_assert(has_iterator_decltype<std::vector<int>>::value, "vector has iterator");
static_assert(!has_iterator_decltype<int>::value, "int doesn't have iterator");
return 0;
}