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

Note for Boost Concept Check Library (BCCL)
===========================================

- [本家ドキュメント(v1.55)](http://www.boost.org/doc/libs/1_55_0/libs/concept_check/concept_check.htm)
- [日本語ドキュメント(v1.30)](http://boost.cppll.jp/BDTJ_1_30/libs/concept_check/concept_check.htm)
- [Reference (v1.55)](http://www.boost.org/doc/libs/1_55_0/libs/concept_check/reference.htm)

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

Index
- [#1 Concept Checking Introduction](http://qiita.com/termoshtt/items/47c8e3a7b2b84b3c883c)
- [#2 Using Concept Checks](http://qiita.com/termoshtt/items/8e91c50dbf299376442f)
- **#3 Creating Concept Checking Classes**
- #4 Concept Covering and Archetypes


## Creating Concept Checking Classes

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

```cpp
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を単にコンセプトと呼ぶ。

#### 他のコンセプトの継承

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

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

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

#### traitsのチェック

```cpp
 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が定義されている事を確認している。

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

これは[前回](http://qiita.com/termoshtt/items/8e91c50dbf299376442f)説明した `BOOST_CONCEPT_ASSERT` で、
使い方もそのままなので略。

#### BOOST_CONCEPT_USAGE

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

```cpp
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`に使用するデータメンバーを

```cpp
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との関係が述べてある。
この部分はおそらく古いので、いずれ調べる。