戻り値で SFINAE

#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_integral.hpp>


template<typename T>
void
func(T,
     typename boost::enable_if<boost::is_integral<T> >::type* = 0
){}


// 戻り値型は、enable_if の第二引数
template<typename T>
typename boost::enable_if<boost::is_integral<T>, void>::type
func2(T){}


struct hoge{
    int value;
};

// operator + は、引数が2つしか渡せないので戻り値型で判断する
template<typename T>
typename boost::enable_if<boost::is_integral<T>, hoge>::type
operator +(hoge& lhs, T rhs){
    hoge result;
    result.value = lhs.value + rhs;
    return result;
}


int
main(){
    
    func(10);         // ok
//  func(0.0f);       // error
    func('a');        // ok
    
    func2(10);        // ok
//  func2(0.0f);      // error
    func2('a');       // ok

    hoge h;
    h + 10;           // ok
//  h + 0.0f;         // error
    h + 'a';          // ok

    return 0;
}


template 関数で、T型を制限する場合、SFINAE を使うテクニックがありますが、その戻り値版です。
引数に enable_if を記述するコードはよく見かけるんですが、戻り値に enable_if を記述するコードは見たことがなかったので書いてみました。
operator + などの演算子オーバーロードは、引数を2つしか渡すことが出来ないので、こういう書き方になるんじゃないでしょか。
個人的にこっちの方がスマートなんだけど何か使われない理由があるか…。
まぁ、複数の条件を付ける場合は、引数で定義したほうが楽そうですね。


[追記]
VC8.0 では、SFINAE が出来ないとコメントを頂いたので試してみたんですが、問題なくコンパイルできたでござる。
試しに VC9.0 も試してみたんですが、こっちも問題なくコンパイル出来ました。
VC7.1 は手元にないので試せない…。
テストコードは、以下のとおり。

template<typename T>
typename boost::enable_if<boost::is_same<T, int>, int>::type
func2(T rhs){
    std::cout << typeid(rhs).name() << ":is int" << std::endl;
    return rhs;
}

template<typename T>
typename boost::enable_if<boost::is_same<T, char>, char>::type
func2(T rhs){
    std::cout << typeid(rhs).name() << ":is char" << std::endl;
    return rhs;
}

template<typename T>
typename boost::enable_if<boost::is_same<T, float>, float>::type
func2(T rhs){
    std::cout << typeid(rhs).name() << ":is float" << std::endl;
    return rhs;
}


[boost]
ver 1.44.0
[参照]
http://d.hatena.ne.jp/faith_and_brave/20081110/1226308533
http://cpplover.blogspot.com/2010/03/decltypesfinae.html