SlideShare a Scribd company logo
1 of 12
Download to read offline
C++コンパイラ
  GCCとClangからの
メッセージをお読みください
お詫びとおことわり
●   うっかり自宅のclangにアクセスできなくして
    しまったので、一部のサンプルコード(のエ
    ラーメッセージ)を掲載できなくなってしまい
    ました。
●   なので実感のつかみにくいかもしれませんがご
    了承ください。
GCCのエラーといえば
                           /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h: In function ‘void
                           std::sort(_RAIter, _RAIter) [with _RAIter = std::_List_iterator<int>]’:
                           prog.cpp:6: instantiated from here
                           /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:4783: error: no
                           match for ‘operator-’ in ‘__last - __first’
                           /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h: In function ‘void
                           std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with
                           _RandomAccessIterator = std::_List_iterator<int>]’:
                           /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:4785: instantiated
#include <list>            from ‘void std::sort(_RAIter, _RAIter) [with _RAIter = std::_List_iterator<int>]’
                           prog.cpp:6: instantiated from here
#include <algorithm>       /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1827: error: no
                           match for ‘operator-’ in ‘__last - __first’
                           /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1829: error: no
                           match for ‘operator+’ in ‘__first + 16’
int main() {               /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1830: error: no
                           match for ‘operator+’ in ‘__first + 16’
    std::list<int> l;      /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h: In function ‘void
                           std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with
                           _RandomAccessIterator = std::_List_iterator<int>]’:
    std::sort(l.begin(),   /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1833: instantiated
                           from ‘void std::__final_insertion_sort(_RandomAccessIterator,
              l.end());    _RandomAccessIterator) [with _RandomAccessIterator = std::_List_iterator<int>]’
                           /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:4785: instantiated
}                          from ‘void std::sort(_RAIter, _RAIter) [with _RAIter = std::_List_iterator<int>]’
                           prog.cpp:6: instantiated from here
                           /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1753: error: no
                           match for ‘operator+’ in ‘__first + 1’
                           /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1833: instantiated
                           from ‘void std::__final_insertion_sort(_RandomAccessIterator,
                           _RandomAccessIterator) [with _RandomAccessIterator = std::_List_iterator<int>]’
                           /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:4785: instantiated
                           from ‘void std::sort(_RAIter, _RAIter) [with _RAIter = std::_List_iterator<int>]’
                           prog.cpp:6: instantiated from here
                           /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1759: error: no
                           match for ‘operator+’ in ‘__i + 1’

 !!!非常に明解で分かりやすい!!!
熟練の暗号解読班の定石手段
●   エラーメッセージから “instantiated from here”
    を探す
●   そこからエラーメッセージを逆に辿りながら、
    実体化された型や関数呼び出しをドキュメント
    と照合する
    ●   テンプレート引数は要件を満たしているか
    ●   実体化されたテンプレートの定義は意図したものか
熟練の暗号解読班の定石手段
●   boost::mpl::eval_if<boost::mpl::apply<boost
    ::remove_reference<boost::mpl::placeholders
    ::……
    ●   perl -ple 's/(?:w+::)*//g'
●   boost::fusion::vector<hoge, fuga, piyo,
    void_, void_, void_, void_, void_, void_,
    void_, ……
    ●   perl -ple 's/,void_//g;'
●   STLfilt
一方新兵はClangを使った
●   ヴィジュアルで位置を指摘してくれる!
        /usr/include/c++/4.3/bits/stl_algo.h:4784:22: error: invalid operands to binary
        expression ('std::_List_iterator<int>' and 'std::_List_iterator<int>')
                                        std::__lg(__last - __first) * 2);
                                                  ~~~~~~ ^ ~~~~~~~


●   マクロ展開後のコードのエラーならそれも追っ
    てくれる! for FOO(1); 'f'
          /tmp/webcompile/_20978_0.cc:6:5: error: no matching function
              call to

                                ^~~
    ●   void f() {}         /tmp/webcompile/_20978_0.cc:2:13: note: instantiated from:
        #define FOO BAR     #define FOO BAR
                                        ^
        #define BAR f
                            /tmp/webcompile/_20978_0.cc:3:13: note: instantiated from:
                            #define BAR f
        int main() {                    ^
            FOO(1);         /tmp/webcompile/_20978_0.cc:1:6: note: candidate function not
        }                   viable: requires 0 arguments, but 1 was provided
                            void f() {}
                                 ^
                            1 error generated.
                                               Clang大勝利!!!
ところが
namespace ns {
    struct z {};
    template<typename T> struct s {};

    template<typename T>
    auto f(s<T> x) -> decltype(f(T())) {
        return f(T());
    }

    template<typename T>
    struct a { static_assert(sizeof(T) && false, "failed"); };

    template<typename T = int>
    auto f(z x) -> decltype(a<T>(), 1) {
        return 0;
    }

    s<s<s<z> > > three;
}

int main() {          これを現行のClangとGCCでコンパイルすると
    f(ns::three);
}                         f(ns::three); の関数呼びだしを解決できなかった
                      という旨のメッセージを吐く
ところが
●   先のコードは、再帰的な実体化を試みた末auto f(z)->
    decltype(a<T>, 0)の実体化に失敗するのが原因
    ●   f(ns::three)の呼び出し解決するためにauto f(s<s<z> >)を実体化しよ
        うとする。
    ●   戻り値の型を求めるためにf(T())の呼び出し解決をしようとする
        –   その呼び出しを解決するためにf(s<z>)を(ry
            ●   その解決のためにf(z)を解決しようとして、失敗する

        –   f(T())の呼び出し解決に失敗する
    ●   f(T())の(ry
    ●   f(ns::three)の呼び出し解決に失敗する
    ●   f(ns::three)の呼び出しがエラーとなる
ところが
●   先のコードは、再帰的な実体化を試みた末auto f(z)->
    decltype(a<T>, 0)の実体化に失敗するのが原因
    ●   f(ns::three)の呼び出し解決するためにauto f(s<s<z> >)を実体化しよ
        うとする。
    ●   戻り値の型を求めるためにf(T())の呼び出し解決をしようとする
        –   その呼び出しを解決するためにf(s<z>)を(ry
            ●   その解決のためにf(z)を解決しようとして、失敗する

        –   f(T())の呼び出し解決に失敗する
    ●   f(T())の(ry
    ●   f(ns::three)の呼び出し解決に失敗する
    ●   f(ns::three)の呼び出しがエラーとなる
老兵再び
●   Clangには呼び出し解決に失敗した場合、各呼び
    出し候補について、その候補が選ばれなかった
    理由を表示する機能がある。
●   GCC4.7にも同様の機能が付いたが、こちらはあ
    る候補の選択されなかった理由が「関数の呼び
    出し解決失敗」である場合、その呼び出しの候
    補と失敗理由についても再帰的に表示してくれ
    る
      GCC(>=4.7)大勝利!!!
まとめ
●   両方でコンパイルできるようにコードを書い
    て、適切に使い分けましょう
問題
●   ドキュメントがない部分(内部実装など)を通る
    と、どの実体化でおかしくなったのか判別する
    ことが困難
    ●   See: PStade.Oven

More Related Content

What's hot

組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
kikairoya
 
C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会
Akihiko Matuura
 
Template Meta Programming入門から応用まで
Template Meta Programming入門から応用までTemplate Meta Programming入門から応用まで
Template Meta Programming入門から応用まで
yoshihikoozaki5
 

What's hot (20)

競技プログラミングのためのC++入門
競技プログラミングのためのC++入門競技プログラミングのためのC++入門
競技プログラミングのためのC++入門
 
C++14 Overview
C++14 OverviewC++14 Overview
C++14 Overview
 
More C++11
More C++11More C++11
More C++11
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
 
C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会
 
Control.Arrow
Control.ArrowControl.Arrow
Control.Arrow
 
Visual C++で使えるC++11
Visual C++で使えるC++11Visual C++で使えるC++11
Visual C++で使えるC++11
 
競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性
 
C++入門?
C++入門?C++入門?
C++入門?
 
C++でHello worldを書いてみた
C++でHello worldを書いてみたC++でHello worldを書いてみた
C++でHello worldを書いてみた
 
Template Meta Programming入門から応用まで
Template Meta Programming入門から応用までTemplate Meta Programming入門から応用まで
Template Meta Programming入門から応用まで
 
C++11
C++11C++11
C++11
 
BoostAsioで可読性を求めるのは間違っているだろうか
BoostAsioで可読性を求めるのは間違っているだろうかBoostAsioで可読性を求めるのは間違っているだろうか
BoostAsioで可読性を求めるのは間違っているだろうか
 
Boost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
Boost.勉強会#19東京 Effective Modern C++とC++ Core GuidelinesBoost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
Boost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
 
F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~
 
C++ tips1 #include編
C++ tips1 #include編C++ tips1 #include編
C++ tips1 #include編
 
unique_ptrにポインタ以外のものを持たせるとき
unique_ptrにポインタ以外のものを持たせるときunique_ptrにポインタ以外のものを持たせるとき
unique_ptrにポインタ以外のものを持たせるとき
 
C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜
C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜
C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜
 
わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61
 
C# 8.0 null許容参照型
C# 8.0 null許容参照型C# 8.0 null許容参照型
C# 8.0 null許容参照型
 

Similar to C++コンパイラ GCCとClangからのメッセージをお読みください

Replace Output Iterator and Extend Range JP
Replace Output Iterator and Extend Range JPReplace Output Iterator and Extend Range JP
Replace Output Iterator and Extend Range JP
Akira Takahashi
 
T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門
伸男 伊藤
 
Wrapping a C++ library with Cython
Wrapping a C++ library with CythonWrapping a C++ library with Cython
Wrapping a C++ library with Cython
fuzzysphere
 
Rのデータ構造とメモリ管理
Rのデータ構造とメモリ管理Rのデータ構造とメモリ管理
Rのデータ構造とメモリ管理
Takeshi Arabiki
 
C++ lecture-1
C++ lecture-1C++ lecture-1
C++ lecture-1
sunaemon
 
Dive into RTS - another side
Dive into RTS - another sideDive into RTS - another side
Dive into RTS - another side
Kiwamu Okabe
 
Php in ruby
Php in rubyPhp in ruby
Php in ruby
do_aki
 
C++ lecture-0
C++ lecture-0C++ lecture-0
C++ lecture-0
sunaemon
 

Similar to C++コンパイラ GCCとClangからのメッセージをお読みください (20)

Replace Output Iterator and Extend Range JP
Replace Output Iterator and Extend Range JPReplace Output Iterator and Extend Range JP
Replace Output Iterator and Extend Range JP
 
Visual C++コード分析を支えるSAL
Visual C++コード分析を支えるSALVisual C++コード分析を支えるSAL
Visual C++コード分析を支えるSAL
 
Altanative macro
Altanative macroAltanative macro
Altanative macro
 
T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門T69 c++cli ネイティブライブラリラッピング入門
T69 c++cli ネイティブライブラリラッピング入門
 
C++ tips 3 カンマ演算子編
C++ tips 3 カンマ演算子編C++ tips 3 カンマ演算子編
C++ tips 3 カンマ演算子編
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISる
 
Wrapping a C++ library with Cython
Wrapping a C++ library with CythonWrapping a C++ library with Cython
Wrapping a C++ library with Cython
 
Rのデータ構造とメモリ管理
Rのデータ構造とメモリ管理Rのデータ構造とメモリ管理
Rのデータ構造とメモリ管理
 
C++ lecture-1
C++ lecture-1C++ lecture-1
C++ lecture-1
 
C++0x総復習
C++0x総復習C++0x総復習
C++0x総復習
 
OCamlのトップレベルあれそれ
OCamlのトップレベルあれそれOCamlのトップレベルあれそれ
OCamlのトップレベルあれそれ
 
Dive into RTS - another side
Dive into RTS - another sideDive into RTS - another side
Dive into RTS - another side
 
Objc lambda
Objc lambdaObjc lambda
Objc lambda
 
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
 
Php in ruby
Php in rubyPhp in ruby
Php in ruby
 
ラズパイでデバイスドライバを作ってみた。
ラズパイでデバイスドライバを作ってみた。ラズパイでデバイスドライバを作ってみた。
ラズパイでデバイスドライバを作ってみた。
 
Brief introduction of Boost.ICL
Brief introduction of Boost.ICLBrief introduction of Boost.ICL
Brief introduction of Boost.ICL
 
C++ lecture-0
C++ lecture-0C++ lecture-0
C++ lecture-0
 
GoらしいAPIを求める旅路 (Go Conference 2018 Spring)
GoらしいAPIを求める旅路 (Go Conference 2018 Spring)GoらしいAPIを求める旅路 (Go Conference 2018 Spring)
GoらしいAPIを求める旅路 (Go Conference 2018 Spring)
 
Prosym2012
Prosym2012Prosym2012
Prosym2012
 

More from digitalghost (7)

拡張可能でprintfっぽい書式指定ができて書式指定文字列と引数をコンパイル時に検証できる文字列フォーマット関数を作った
拡張可能でprintfっぽい書式指定ができて書式指定文字列と引数をコンパイル時に検証できる文字列フォーマット関数を作った拡張可能でprintfっぽい書式指定ができて書式指定文字列と引数をコンパイル時に検証できる文字列フォーマット関数を作った
拡張可能でprintfっぽい書式指定ができて書式指定文字列と引数をコンパイル時に検証できる文字列フォーマット関数を作った
 
Define and expansion of cpp macro
Define and expansion of cpp macroDefine and expansion of cpp macro
Define and expansion of cpp macro
 
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
 
No skk, no life.
No skk, no life.No skk, no life.
No skk, no life.
 
Boost.Preprocessorでプログラミングしましょう
Boost.PreprocessorでプログラミングしましょうBoost.Preprocessorでプログラミングしましょう
Boost.Preprocessorでプログラミングしましょう
 
テンプレートメタプログラミング as 式
テンプレートメタプログラミング as 式テンプレートメタプログラミング as 式
テンプレートメタプログラミング as 式
 
Preprocess-time Lambda Expression
Preprocess-time Lambda ExpressionPreprocess-time Lambda Expression
Preprocess-time Lambda Expression
 

C++コンパイラ GCCとClangからのメッセージをお読みください

  • 2. お詫びとおことわり ● うっかり自宅のclangにアクセスできなくして しまったので、一部のサンプルコード(のエ ラーメッセージ)を掲載できなくなってしまい ました。 ● なので実感のつかみにくいかもしれませんがご 了承ください。
  • 3. GCCのエラーといえば /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h: In function ‘void std::sort(_RAIter, _RAIter) [with _RAIter = std::_List_iterator<int>]’: prog.cpp:6: instantiated from here /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:4783: error: no match for ‘operator-’ in ‘__last - __first’ /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h: In function ‘void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = std::_List_iterator<int>]’: /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:4785: instantiated #include <list> from ‘void std::sort(_RAIter, _RAIter) [with _RAIter = std::_List_iterator<int>]’ prog.cpp:6: instantiated from here #include <algorithm> /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1827: error: no match for ‘operator-’ in ‘__last - __first’ /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1829: error: no match for ‘operator+’ in ‘__first + 16’ int main() { /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1830: error: no match for ‘operator+’ in ‘__first + 16’ std::list<int> l; /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h: In function ‘void std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = std::_List_iterator<int>]’: std::sort(l.begin(), /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1833: instantiated from ‘void std::__final_insertion_sort(_RandomAccessIterator, l.end()); _RandomAccessIterator) [with _RandomAccessIterator = std::_List_iterator<int>]’ /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:4785: instantiated } from ‘void std::sort(_RAIter, _RAIter) [with _RAIter = std::_List_iterator<int>]’ prog.cpp:6: instantiated from here /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1753: error: no match for ‘operator+’ in ‘__first + 1’ /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1833: instantiated from ‘void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = std::_List_iterator<int>]’ /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:4785: instantiated from ‘void std::sort(_RAIter, _RAIter) [with _RAIter = std::_List_iterator<int>]’ prog.cpp:6: instantiated from here /usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/stl_algo.h:1759: error: no match for ‘operator+’ in ‘__i + 1’ !!!非常に明解で分かりやすい!!!
  • 4. 熟練の暗号解読班の定石手段 ● エラーメッセージから “instantiated from here” を探す ● そこからエラーメッセージを逆に辿りながら、 実体化された型や関数呼び出しをドキュメント と照合する ● テンプレート引数は要件を満たしているか ● 実体化されたテンプレートの定義は意図したものか
  • 5. 熟練の暗号解読班の定石手段 ● boost::mpl::eval_if<boost::mpl::apply<boost ::remove_reference<boost::mpl::placeholders ::…… ● perl -ple 's/(?:w+::)*//g' ● boost::fusion::vector<hoge, fuga, piyo, void_, void_, void_, void_, void_, void_, void_, …… ● perl -ple 's/,void_//g;' ● STLfilt
  • 6. 一方新兵はClangを使った ● ヴィジュアルで位置を指摘してくれる! /usr/include/c++/4.3/bits/stl_algo.h:4784:22: error: invalid operands to binary expression ('std::_List_iterator<int>' and 'std::_List_iterator<int>') std::__lg(__last - __first) * 2); ~~~~~~ ^ ~~~~~~~ ● マクロ展開後のコードのエラーならそれも追っ てくれる! for FOO(1); 'f' /tmp/webcompile/_20978_0.cc:6:5: error: no matching function call to ^~~ ● void f() {} /tmp/webcompile/_20978_0.cc:2:13: note: instantiated from: #define FOO BAR #define FOO BAR ^ #define BAR f /tmp/webcompile/_20978_0.cc:3:13: note: instantiated from: #define BAR f int main() { ^ FOO(1); /tmp/webcompile/_20978_0.cc:1:6: note: candidate function not } viable: requires 0 arguments, but 1 was provided void f() {} ^ 1 error generated. Clang大勝利!!!
  • 7. ところが namespace ns { struct z {}; template<typename T> struct s {}; template<typename T> auto f(s<T> x) -> decltype(f(T())) { return f(T()); } template<typename T> struct a { static_assert(sizeof(T) && false, "failed"); }; template<typename T = int> auto f(z x) -> decltype(a<T>(), 1) { return 0; } s<s<s<z> > > three; } int main() { これを現行のClangとGCCでコンパイルすると f(ns::three); } f(ns::three); の関数呼びだしを解決できなかった という旨のメッセージを吐く
  • 8. ところが ● 先のコードは、再帰的な実体化を試みた末auto f(z)-> decltype(a<T>, 0)の実体化に失敗するのが原因 ● f(ns::three)の呼び出し解決するためにauto f(s<s<z> >)を実体化しよ うとする。 ● 戻り値の型を求めるためにf(T())の呼び出し解決をしようとする – その呼び出しを解決するためにf(s<z>)を(ry ● その解決のためにf(z)を解決しようとして、失敗する – f(T())の呼び出し解決に失敗する ● f(T())の(ry ● f(ns::three)の呼び出し解決に失敗する ● f(ns::three)の呼び出しがエラーとなる
  • 9. ところが ● 先のコードは、再帰的な実体化を試みた末auto f(z)-> decltype(a<T>, 0)の実体化に失敗するのが原因 ● f(ns::three)の呼び出し解決するためにauto f(s<s<z> >)を実体化しよ うとする。 ● 戻り値の型を求めるためにf(T())の呼び出し解決をしようとする – その呼び出しを解決するためにf(s<z>)を(ry ● その解決のためにf(z)を解決しようとして、失敗する – f(T())の呼び出し解決に失敗する ● f(T())の(ry ● f(ns::three)の呼び出し解決に失敗する ● f(ns::three)の呼び出しがエラーとなる
  • 10. 老兵再び ● Clangには呼び出し解決に失敗した場合、各呼び 出し候補について、その候補が選ばれなかった 理由を表示する機能がある。 ● GCC4.7にも同様の機能が付いたが、こちらはあ る候補の選択されなかった理由が「関数の呼び 出し解決失敗」である場合、その呼び出しの候 補と失敗理由についても再帰的に表示してくれ る GCC(>=4.7)大勝利!!!
  • 11. まとめ ● 両方でコンパイルできるようにコードを書い て、適切に使い分けましょう
  • 12. 問題 ● ドキュメントがない部分(内部実装など)を通る と、どの実体化でおかしくなったのか判別する ことが困難 ● See: PStade.Oven