6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

一人でBoost勉強会:Concept Check #3

Posted at

Note for Boost Concept Check Library (BCCL)

以下の記述は公式のドキュメントを自分なりに要約した物であり、
和訳を目指す物ではない。
また内容を保証するものでもない。

Index

Creating Concept Checking Classes

いよいよ実際にコンセプトをチェックするクラスを実装する部分を説明する。
ここではまず入力反復子(InputIterator)である事を確認するクラスを作成する。
今まではあるイテレータがある時、それが入力反復子である事を厳密に確認する手段はなかった。
次に示すテンプレートクラスは入力演算子の厳密な定義を与える:

template <class X>
struct InputIterator
  : Assignable<X>, EqualityComparable<X>
{
 private:
    typedef std::iterator_traits<X> t;
 public:
    typedef typename t::value_type value_type;
    typedef typename t::difference_type difference_type;
    typedef typename t::reference reference;
    typedef typename t::pointer pointer;
    typedef typename t::iterator_category iterator_category;

    BOOST_CONCEPT_ASSERT((SignedInteger<difference_type>));
    BOOST_CONCEPT_ASSERT((Convertible<iterator_category, std::input_iterator_tag>));
        
    BOOST_CONCEPT_USAGE(InputIterator)
    {
        X j(i);             // require copy construction
        same_type(*i++,v);  // require postincrement-dereference returning value_type
        X& x = ++j;         // require preincrement returning X&
    }
    
 private:
    X i;
    value_type v;

    // Type deduction will fail unless the arguments have the same type.
    template <typename T>
    void same_type(T const&, T const&);
};

以降ではこのようなconcept checking classを単にコンセプトと呼ぶ。

他のコンセプトの継承

template <class X>
struct InputIterator
  : Assignable<X>, EqualityComparable<X>

まずこの部分を考えよう。
あるコンセプトを実装しようと思う時、その全ての条件が独自である事は少ないだろう。
特に自作のライブラリ内のコンセプトだとなおさらである。
この時、既に存在しているコンセプトを利用できると嬉しいし、そうすべきである。
BCCLではこれをテンプレートクラスの継承を利用して実現する。

まず入力演算子は代入可能(Assignable)で、比較可能(EqualityComparable)である必要がある。
この部分を上述の継承の部分で実装している。
もしInputIteratorクラスの本体の実装せずとも、クラスXがAssignableでEqualityComparableである事がテストされる。

traitsのチェック

 private:
    typedef std::iterator_traits<X> t;
 public:
    typedef typename t::value_type value_type;
    typedef typename t::difference_type difference_type;
    typedef typename t::reference reference;
    typedef typename t::pointer pointer;
    typedef typename t::iterator_category iterator_category;

これはtraitsが定義されている事を確認している。

BOOST_CONCEPT_ASSERT((SignedInteger<difference_type>));
BOOST_CONCEPT_ASSERT((Convertible<iterator_category, std::input_iterator_tag>));

これは前回説明した BOOST_CONCEPT_ASSERT で、
使い方もそのままなので略。

BOOST_CONCEPT_USAGE

これがkeyとなる部分だろう。

BOOST_CONCEPT_USAGE(InputIterator)
{
    X j(i);             // require copy construction
    same_type(*i++,v);  // require postincrement-dereference returning value_type
    X& x = ++j;         // require preincrement returning X&
}

これはsyntaxが有効かどうかを調べている。実際にこのコードが実行される事はない。

at this point you may sometimes need to be a little creative

と言っている通り、この部分を実装するのがもっとも大変だろう。
例えば*i++X型を返す事を確認するために、補助関数same_typeを導入している。
この部分はTMP用のライブラリを使用する方がいいだろう。

Values for Usage Patterns Should Be Data Members

ここでBOOST_CONCEPT_USAGEに使用するデータメンバーを

X i;
value_type v;

のようにデータメンバーとして定義するのは、
Xがデフォルトコンストラクタを持たなくてもよくなるためである。

since instances of the InputIterator template will never be constructed, the compiler never has to check how its data members will be constructed (C++ Standard Section 14.7.1 9)

とある通り、データメンバーは初期化されないので、
BOOST_CONCEPT_USAGEで使用するインスタンスはデータメンバーとして定義する必要がある。

Similarity to Proposed C++0x Language Support for Concepts

他の提案されているsyntaxとの関係が述べてある。
この部分はおそらく古いので、いずれ調べる。

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?