C++と色々

主にC++やプログラムに関する記事を投稿します。

Visual C++ 12.0で boost iterator concepts がコンパイルエラーになる

以下のコードがVisual C++ 12.0でコンパイルエラーになります。Boostのバージョンは1.55です。

#include <boost/iterator/iterator_concepts.hpp>

int main()
{
}

出力 http://melpon.org/wandbox/permlink/oJdAALJZbyRJgIiG

iterator_concepts.hpp(43): error C2448: 'BOOST_concept' : 関数の定義が間違っています。

この辺りを見た感じ、BOOST_conceptマクロ展開が怪しそうなので、/EPコンパイラプションをつけてマクロを展開したソースコードをチェックしてみました。

マクロ展開したソースコードの一部抜粋

         namespace boost_concepts
         {
           
           
           
         
           
           
         
           BOOST_concept(ReadableIterator,(Iterator))
             : boost::Assignable<Iterator>
             , boost::CopyConstructible<Iterator>
         
           {
               typedef typename boost::detail::iterator_traits<Iterator>::value_type value_type;
               typedef typename boost::detail::iterator_traits<Iterator>::reference reference;
         
               enum { boost_concept_check50 = sizeof(::boost::concepts::require_((void(*)(boost::concepts::usage_requirements<ReadableIterator>))0)) }; ~ReadableIterator()
               {
         
                   value_type v = *i;
                   boost::ignore_unused_variable_warning(v);
               }
           private:
               Iterator i;
           };

BOOST_conceptが展開されていませんでした。定義されてから使用されるまでの間にundefされてしまっているようです。しかし、ソースコードを見ても

<boost/iterator/iterator_concepts.hpp>
↓
    <boost/concept_check.hpp>
    BOOST_concept defineされる
    ↓
    BOOST_concept undefされる
    <boost/concept_check.hpp>おわり
↓
BOOST_concept defineされる
↓
BOOST_concept使用
↓
BOOST_concept undefされる
↓
<boost/iterator/iterator_concepts.hpp>おわり

と、undefされているように見えないんですよね…

もしかして一度undefしてしまうと、再度defineしてもundefされたままと見なして展開してくれない、プリプロセッサの不具合ではないかと思ったのですが、

#define A typename T
#undef A
#define A typename T
template < A >
struct hoge {};
#undef A

int main()
{
    hoge<int> h;
}

が普通に動いたのでそれはなさそうです。 Visual C++では<boost/concept/detail/concept_undef.hpp>の、

# undef BOOST_concept_typename
# undef BOOST_concept

をコメントアウトするか、もしくは<boost/concept_check.hpp>の一番最後から3行目、1082行目の

# include <boost/concept/detail/concept_undef.hpp>

をコメントアウトすることで、最初のソースコードのコンパイルが通ります。

本当の原因は結局わかりませんでした。


ちなみにclangとgccは最初のソースコードのコンパイル通ります。(gccは警告がたくさん出ますが)