C ++ 11で自動とdecltypeを使用して
質問
私はC ++ 11の現在受け入れられている機能を習得しようとしていると私は自動車やdecltypeとのトラブルを抱えています。学習練習として、私はいくつかの一般的な機能を持つSTDクラスのリストを拡張しています。
template<class _Ty, class _Ax = allocator<_Ty>>
class FList : public std::list<_Ty, _Ax>
{
public:
void iter(const function<void (_Ty)>& f)
{
for_each(begin(), end(), f);
}
auto map(const function<float (_Ty)>& f) -> FList<float>*
{
auto temp = new FList<float>();
for (auto i = begin(); i != end(); i++)
temp->push_back(f(*i));
return temp;
}
};
auto *ints = new FList<int>();
ints->push_back(2);
ints->iter([](int i) { cout << i; });
auto *floats = ints->map([](int i) { return (float)i; });
floats->iter([](float i) { cout << i; });
メンバーマップについては、私は戻り値の型が渡された関数が返すものに応じて汎用的なものにしたいです。だから、戻り値の型のために、私はこのような何かを行うことができます。
auto map(const function<float (_Ty)>& f) -> FList<decltype(f(_Ty))>*
これはまた、関数テンプレートにfloat型を削除する必要があります。
auto map(const function<auto (_Ty)>& f) -> FList<decltype(f(_Ty))>*
私は、テンプレートクラスを使用することができますが、私は戻り値の型を指定する必要があるため、それはインスタンスの使用がより冗長になります。
template<class T> FList<T>* map(const function<T (_Ty)>& f)
私の質問の合計に私は、テンプレートクラスを使用せずにマップを定義し、まだそれが返すタイプで、それは一般的な持っているかを把握しようとしている。
解決
std::list
または他のstd::
容器に由来するが推奨されます。
あなたの業務として自由な機能を記述します。
あなたは「テンプレート機能を使用せずにマップを定義する」を意味するのですか?
あなたはそれを返すタイプを取得するためにresult_type
のstd::function
メンバーの種類を使用することができる必要があります。
std::function
として渡されることを指定するためにまた、それは必要はありません。あなたはどのようなタイプとして、それを開いたまま、コンパイラがすべてを参加してみましょうことができます。あなただけのランタイム多型についてstd::function
を必要とします。
と生ヒープ割り当てオブジェクトを作成するための新しい使用してポインタでそれらを返すにはサイコー1992です! :)
あなたのITER機能は、基本的にhref="http://en.wikipedia.org/wiki/C%2B%2B0x#Range-based_for-loop" rel="noreferrer">レンジ・のベースます。
しかし、すべてはさておき、その...あなたはこのような何かを意味していますか?
template <class TFunc>
auto map(const TFunc &f) -> FList<decltype(f(_Ty()))>*
{
auto temp = new FList<decltype(f(_Ty()))>();
for (auto i = begin(); i != end(); i++)
temp->push_back(f(*i));
return temp;
}
これは何も呼び出し可能一致し、decltypeを使用して、関数の戻り値の型を把握します。
これはデフォルト構築可能であることを_Tyが必要であることに注意してください。あなたは、インスタンスを製造することにより、その周りを取得することができます:
template <class T>
T make_instance();
何のコードが生成されませんので、何実装は、リンカーは文句を言うことは何もありませんので、それを呼び出す必要はありません(これを指摘してdribeasに感謝を!)
だから、コードは現在次のようになります。
FList<decltype(f(make_instance<_Ty>()))>*
文字通りまたは、タイプはあなたが_Tyのインスタンスを参照して、関数fを呼び出してから取得したいだろう何のリストます。
そして受け入れるための無料ボーナスとして、右辺値参照をルックアップする - これらは、あなたが書くことができることを意味します。
std::list<C> make_list_somehow()
{
std::list<C> result;
// blah...
return result;
}
そして、このようにそれを呼び出します:
std::list<C> l(make_list_somehow());
のstd ::リストは、(コピーコンストラクタようですが、引数は、ここのように、一時的なものであるとき、選ばれた)「移動コンストラクタ」を持って、それはすなわち最適と同じ操作を行い、戻り値の内容を盗むことができますのでswap
。だから、リスト全体のないコピーはありません。 (これはC ++ 0xのが速く単純に書かれた既存のコードの実行を行います理由です - 多くの人気醜いパフォーマンスのトリックが時代遅れになるだろう)。
そして、あなたはunique_ptr
を使用することにより、正しい動きのコンストラクタを記述することなく、あなた自身の既存のクラスに無料のものと同じ種類を取得することができます。
std::unique_ptr<MyThing> myThing(make_my_thing_somehow());
他のヒント
あなたは引数の型を推定することにしたい関数の引数にautoを使用することはできません。あなたはそのためのテンプレートを使用します。見て: http://thenewcpp.wordpress.com/2011/10/18/ - キーワード自動/ と http://thenewcpp.wordpress.com/2011/10/25/ decltype-と-declval / に。これらは両方とも自動とdecltypeを使用する方法について説明します。彼らはあなたに彼らがどのように使用されるかについての十分な情報を与える必要があります。特に、make_instanceについて別の答えはdeclvalとのより良い行うことができます。
私はJarrahは彼の答えになっていたそのポイントは、これらの点は、これらのものを使用して正確にどのように説明しないということだと思います。私はとにかく細部を指摘します:
あなたはこれを行うことはできません、間違った二つのものがあります
auto map(const function<auto (_Ty)>& f) -> FList<decltype(f(_Ty))>*
auto
は、関数の引数には使用できません。あなたは、関数の種類を推定することにしたいなら、あなたは、テンプレートを使用する必要があります。第二のタイプはdecltype
ある一方_Ty
は、式を取ることです。ここではそれを解決する方法です。
template <typename Ret>
auto
map(const function<Ret (_Ty)>& f)
-> FList<decltype(f(declval<_Ty>()))>
{}
その方法は、型のインスタンスを作成するための魔法はありません。