http://tinyurl.com/3f6sw
を参考にしてみる.以下はVC++7.1で動作確認済み.
#include <iostream> template<class T> struct delayed; template<class T> struct error_if_const; template<class T> struct error_if_const<T const> { typedef typename delayed<T>::error type; }; template<class T> void f(T const &) // #1 { std::cout << "rvalue" << std::endl; } template<class T> void f(T &, typename error_if_const<T>::type = 0); // #2 template<class T> void f(T &) // #3 { BOOST_STATIC_ASSERT(false); } int g(){ return 0; } int const h(){ return 0; } int main() { int i = 0; const int ci = 0; f(1); // #A: OK rvalue(literal) f(g()); // #B: OK rvalue(temporary) f(i); // #C: コンパイルエラー lvalue f(ci); // #D: コンパイルエラー const lvalue f(h()); // #E: コンパイルエラー const rvalue return 0; }
( ゜∀゜)アハハ八八ノヽノヽノヽノ \ / \/ \
って,おいおいおいおいマテマテマテマテ・・・なんじゃこのSFINAEは!?const参照と一時変数を区別してる!?自分で書いておいてなんだがありえん・・・.
- #A:overload resolutionの結果#1を選択
- #B:#Aと同様
- #C:#2はSFINAEでoverload resolutionから除外される.#1(T = int)と#3(T = int)からoverload resolutionにより#3が選択.結果BOOST_STATIC_ASSERTで弾かれる
- #D:overload resolutionの段階で#2をT = int constでinstantiationしようとする(で,substitutionも成功する)ため,遅延発生させたsubstitution failureでコンパイルエラーを引き起こす.ただし,#2(T = int const)のinstantiationが成功するコードの場合でも選択されるのは#1(T = int)であることに注意(よってdispatchは不可能か)
- #E:#Dと同様
あくまでdispatchは出来ない訳ね.ま,それが出来たらどえらいことになるんだけど.copy semanticsをコンパイルエラーで弾いて,move semanticsのみを選択的に透過することは出来ると.これでmove semanticsのみを持つ型を安全に提供できるのか・・・.
あまりに変態すぎて呆れて物も言えんわw.