c++11コンパイル時のタイプ判定

5045 ワード

c++11には特殊なテンプレートクラスintegral_があります.constant、まず実現を見ます.
  template
    struct integral_constant
    {
      static constexpr _Tp                  value = __v;
      typedef _Tp                           value_type;
      typedef integral_constant<_tp __v="">   type;
      constexpr operator value_type() const { return value; }
#if __cplusplus > 201103L

#define __cpp_lib_integral_constant_callable 201304

      constexpr value_type operator()() const { return value; }
#endif
    };

コードは簡単です.いくつかのことをしました.定義は1つです.TPタイプのvalueメンバー変数であり、値を__とするv,typedefでvalue_を宣言したtypeとtype、value_をリロードしましたtypeと()オペレータ.簡単に使用できます.
typedef std::integral_constant two_t;
typedef std::integral_constant four_t;
typedef std::integral_constant five_t;
static_assert(two_t::value*2 == four_t::value, "always true");
static_assert(two_t::value*2 == five_t::value, "always false");
オーブンには特別な場所はないように見えますが、実際にはテンプレートメタプログラミングにとって、その用途は大きくなり、STLでは多くの場所で使われています.type_traitsで定義されている非常に重要な2つのintegral_constantタイプ:
 /// The type used as a compile-time boolean with true value.
  typedef integral_constant     true_type;

  /// The type used as a compile-time boolean with false value.
  typedef integral_constant    false_type;

    true_typeは定数trueの包装クラス、false_typeは定数falseの包装クラスである.従来の定数との最大の違いは、クラスタイプであり、継承によって使用できます.たとえば、次のようになります.
class IamTrue : public true_type {
};

cout << IamTrue::value << endl; // 1

次に、c++がコンパイル時にタイプ判断を行う方法を見ます.
template struct is_same : public false_type { };
template struct is_same<_tp _tp="">: public true_type { 
class TestA{};
typedef TestA ToTestA;
class TestB{};
int main() {
    cout << is_same::value << endl; // 1
    cout << is_same::value << endl; // 0
    return 0;
} 

ここではなぜこのような結果になったのかを説明し、まず最初のコンパイル時にc++のコンパイル時選択性により、最初のテンプレートクラスが要求に合致することを発見したためtrueを返し、2番目のコンパイル時にパラメータが同じタイプではないためfalse_を選択したtype.type_traitsヘッダファイルには、類似の機能が複雑なテンプレートクラスが多く、コンパイル時の選択性を利用しており、コンパイルによって決定されるため、実行時の消費はありません.
次に、クラスが純虚クラスであることをどのように判断するかを見てみましょう.参考:クリックしてリンクを開く
struct __two{char __lx[2];};
namespace _is_abstract
{
    template  char  __test(_Tp (*p)[1]);
    template  __two __test(...);
}
    __is_abstract_impネーミングスペースには2つのリロードされたテンプレート関数が宣言され、戻り値はcharと__である.two.この2つの関数を宣言する意味は、コンパイル期間のリロード関数のマッチングによって、入力されたテンプレートパラメータが私たちの要求に合っているかどうかを判断することができ、判断の仕方も簡単で、sizeofオペレータを使用すればいいということです.
#define __is_abstract_(_T)  sizeof(_is_abstract::__test<_t>(0)) == 2
template   
struct is_abstract_imp  : public integral_constant    { };
    , ,sizeof 1, sizeof 2, 。

     , p _TP ( ), [1] , 1, , 0, , 0 。 , , ( , TP a[1], TP* a[1]), , , 。

class A {
};

class B {
public:
    virtual void Say() = 0;
};

int main()
{
    std::cout << is_abstract_imp::value << '';
std::cout << is_abstract_imp::value << '';
return 0;
}

    , , , 。 , , , , :   

namespace __is_abstract_imp
{
	template  char  __test(_Tp);
	template  __two __test(...);
}
     sizeof , sizeof , _TP , __test , 0 , 。