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

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** 
- #3 Creating Concept Checking Classes
- #4 Concept Covering and Archetypes

Using Concept Checks
--------------------

#### BOOST_CONCEPT_ASSERT()

コンセプトを満しているかを確認するマクロ。
cassertのassertに相当する。

```cpp:boost_concept_assert.cpp
#include "boost/concept_check.hpp"

template<typename T>
void generic_function(T x){
    BOOST_CONCEPT_ASSERT((boost::EqualityComparable<T>));
    // Do something
}
class foo{};
int main(){
    int i = 2;
    double a = 1.0;
    generic_function(i);
    generic_function(a);

    foo f;
    generic_function(f);
    return 0;
}
```

g++ (GCC) 4.8.2 20131212 (Red Hat 4.8.2-7) で動作を確認している:

```
In file included from ./boost_concept_assert.cpp:2:0:
/usr/include/boost/concept_check.hpp: In instantiation of ‘boost::EqualityComparable<TT>::~EqualityComparable() [with TT = foo]’:
/usr/include/boost/concept/detail/general.hpp:39:28:   required from ‘static void boost::concepts::requirement<boost::concepts::failed************ Model::************>::failed() [with Model = boost::EqualityComparable<foo>]’
./boost_concept_assert.cpp:6:5:   required from ‘void generic_function(T) [with T = foo]’
./boost_concept_assert.cpp:17:23:   required from here
/usr/include/boost/concept_check.hpp:237:30: エラー: no match for ‘operator==’ (operand types are ‘foo’ and ‘foo’)
       require_boolean_expr(a == b);
                              ^
/usr/include/boost/concept_check.hpp:238:30: エラー: no match for ‘operator!=’ (operand types are ‘foo’ and ‘foo’)
       require_boolean_expr(a != b);
                              ^
```

このように合同を判定するoperator (==, !=)が実装されていない場合、
コンパイル時にエラーとなる。
`./boost_concept_assert.cpp:17:23:   required from here`
のように何処で問題が生じたか出力される上、比較演算子が無い旨がエラーメッセージに表示されている。
初心者にはまだ辛い表示だが。

ここで括弧が2重に必要な理由だが、本文では、

> You can use this macro at any scope,
> by passing a concept checking template specialization enclosed in parentheses.
> Note: that means invocations of BOOST_CONCEPT_ASSERT will appear to use double parentheses.

とあるのみである。
ヘッダを読んだ感じ、以下のコードに相当する事をしている：

```cpp
#define DEF(ARG) void(*)ARG

template<class Func>
class F{};

int main(){
    F<DEF((double))> f;
    return 0;
}
```

`DEF((double))`が関数ポインタ`void(*)(double)`に展開されているのである。
`BOOST_CONCEPT_ASSERT`が`DEF`に相当し、関数ポインタを用いてTMPで変換可能がを判定している。
要は型だけを記述する構文が許されるのは関数ポインタの定義時だという事を用いている。

#### BOOST_CONCEPT_REQUIRES

C++11では採用されなかったが、
以下のように、テンプレート引数の`class`, `typename`の代りに
conceptを記述する書き方が提案されていた:
[syntax for declaring concept constrained function templates](http://www.generic-programming.org/languages/conceptcpp/tutorial)

```cpp
#include <concepts>
template<std::CopyConstructible T>
T sum(T array[], int n)
{
  T result = 0;
  for (int i = 0; i < n; ++i)
    result = result + array[i];
  return result;
}
```

これに相当する事を既存の言語仕様下で実行するための方法が`BOOST_CONCEPT_REQUIRES`である。
ドキュメントには以下のようなコードがある:

```cpp
template<typename RanIter>
BOOST_CONCEPT_REQUIRES(
    ((Mutable_RandomAccessIterator<RanIter>))
    ((LessThanComparable<typename Mutable_RandomAccessIterator<RanIter>::value_type>)),
    (void)) // return type
    stable_sort(RanIter,RanIter);
```

これを解読するためには、まず

```cpp
BOOST_CONCEPT_REQUIRES(
    ((Mutable_RandomAccessIterator<RanIter>))
    ((LessThanComparable<typename Mutable_RandomAccessIterator<RanIter>::value_type>)),
    (void))
```

が`RanIter`が適切な時、型`void`になる事を理解する必要がある。
つまり

```cpp
template<typename RanIter>
void stable_sort(RanIter, RanIter);
```

の`void`の部分にむりやり`BOOST_CONCEPT_ASSERT`に相当する物を埋め込んだのである。
これにより、関数の呼び出しの位置でエラーが発生する。

### Multi-Type Concepts

2つ以上の型が関係するコンセプトも同様に定義できる。
同じなので略。

このようなコンセプトチェック機構はジェネリックライブラリの実装者のための物だが、

```cpp
BOOST_CONCEPT_ASSERT((BidirectionalIterator<std::list<int>::iterator>));
```

のようにエンドユーザーが`list<int>`が双方向イテレータがどうか調べるためにも使える。