C++:function-pointerとfunction-reference

昨日、アキラ大先生がつぶやいて曰く、

「void f(int) があるとき、Ovenの中身では f と &f が区別される」
<http://twitter.com/cpp_akira/status/7397358542>
<http://twitter.com/cpp_akira/status/7397772303>

…mjdsk…!

まずは、事態を把握するために適当実験…

#include <iostream>
#include <vector>
#include <pstade/oven/initial_values.hpp>
#include <pstade/oven/algorithm.hpp>

void show(int x) { std::cout << x << std::endl; }
int main()
{
const std::vector<int> v = pstade::oven::initial_values(1, 2, 3, 4, 5);
pstade::oven::for_each(v, &show); // OK
// pstade::oven::for_each(v, show); // NG
}

…うわぉ。


となると、OKとNGを腑分けるメカニズムが何ぞあるはずです。


Ovenの中身を覗いてピンと来たのが以下のコード。


// \pstade\egg\detail\meta_arg.hpp
/*略*/
// rvalue
template<class A>
struct meta_carg
{
typedef A const type;
};

// lvalue
template<class A>
struct meta_carg<A&>
{
typedef A const type;
};
/*略*/

ふむ。なんかごにょれば切り分けられそうな気がしてきたざます。


というわけでちょいちょいと。


#include <iostream>
template < class R >
void test( R(*)(void) )
{
std::cout << "function-pointer" << std::endl;
}

template < class R >
void test( R(&)(void) )
{
std::cout << "function-reference" << std::endl;
}

void f() {};

int main()
{
test( f ); // function-reference
test( &f ); // function-pointer
return 0;
}

…イケました。

あとはboost::type_traitsやらboost::mplやらに頑張っていただければコンパイルタイムにfunction-pointerとfunction-referenceを腑分けることができるはず…。


0 コメント: