rvalueのみを選択的に透過するSFINAE

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.