ページ 11

boost::functionとオーバーロードされた関数

Posted: 2013年5月30日(木) 04:46
by SUE
おはようございます。早速ですが質問です。

今回この記事などを参考に、make_sharedをfunctionに代入する以下のコードを書いてみました。

コード:

#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

struct A{
	A( int ){}

private:
	A();//sealed
};

int main()
{
	boost::shared_ptr<A> (*f)( int ) = static_cast< boost::shared_ptr<A> (*)( int ) >( &boost::make_shared );
	return 0;
}
しかし、明示的に型を示したにもかかわらず、「オーバーロードされた関数を特定できない」という旨のエラーが吐かれます。
どう解決すればよいのでしょうか、ご教示お願いします。

Re: boost::functionとオーバーロードされた関数

Posted: 2013年5月30日(木) 08:52
by beatle
static_castを通常のCスタイルキャストにし、&boost::make_sharedを&boost::make_shared<A, int>にしたら解決するようです。

Re: boost::functionとオーバーロードされた関数

Posted: 2013年5月30日(木) 13:48
by YuO
SUE さんが書きました:しかし、明示的に型を示したにもかかわらず、「オーバーロードされた関数を特定できない」という旨のエラーが吐かれます。
boostのヘッダを見たわけではないですが,http://www.boost.org/doc/libs/1_53_0/li ... hared.htmlを見ると,

コード:

shared_ptr<A> make_shared (int);
に適合するmake_sharedはなく,make_shared<A>(1)は,

コード:

shared_ptr<A> make_shared (int &&);
若しくは

コード:

shared_ptr<A> make_shared (int const &);
が使われているように思えます。
なので,

コード:

auto f = static_cast< boost::shared_ptr<A> (*)( int && ) >( &boost::make_shared );
若しくは

コード:

boost::shared_ptr<A> (*f)( int && ) = boost::make_shared;
若しくは

コード:

auto f = static_cast< boost::shared_ptr<A> (*)( int const & ) >( &boost::make_shared );
若しくは

コード:

boost::shared_ptr<A> (*f)( int const & ) = boost::make_shared;
とすればよいかと思います。
# C++11の右辺値参照と可変長引数テンプレートをサポートしているか否かで関数テンプレートの定義が異なります。
beatle さんが書きました:static_castを通常のCスタイルキャストにし、&boost::make_sharedを&boost::make_shared<A, int>にしたら解決するようです。
Cスタイルキャストは規則としてreinterpret_castを含む危険なキャストであるため,本来適合しない型であってもキャストを通してしまいます。
今回は,明示的なテンプレートの解決を行って関数を一つに絞った上で,型が異なるために強引にreinterpret_castで型を合わせてしまっているのだと思います。
# &boost::make_shared<A, int>にしたなら,キャストせずにautoなり正規の型でそのまま受ければよいと思う。

Re: boost::functionとオーバーロードされた関数

Posted: 2013年5月30日(木) 14:24
by h2so5
g++4.2.1 と clang++3.0 と g++4.6.3 で試しましたが、static_castを使ったときにビルドが通るのはg++4.6.3だけでした。
古いコンパイラではコンパイルエラーになるようです。

Re: boost::functionとオーバーロードされた関数

Posted: 2013年5月30日(木) 22:24
by SUE
みなさんありがとうございます。僕の使っているコンパイラはVC++v120ですが、残念ながらYuOさんに挙げていただいたどの方法を使ってもコンパイルは通りませんでした。
オーバーロードされた関数に&を付けると型なしになるという例外的な扱いだけに、正しく処理するのも難しいようですね。

今回は本筋のプログラムは別の方法を使って解決できそうなので、この件はここまでで解決とさせて頂きます。改めて回答ありがとうございました。