web-dev-qa-db-ja.com

可変長テンプレートテンプレートと完全な転送

この質問オブジェクトジェネレータパターン は、自動化する方法について考えさせられましたそれ。

基本的に、_std::make_pair_、_std::bind1st_、_std::mem_fun_のような関数の作成を自動化し、テンプレートクラスタイプごとに異なる関数を作成する代わりに、単一の変数を作成できるようにします。すべてのケースを一度に処理するテンプレートテンプレート関数。この関数の使用方法は次のとおりです。

_make<std::pair>(1, 2);         // equivalent to std::make_pair(1, 2)
make<std::binder2nd>(&foo, 3); // equivalent to std::bind2nd(&foo, 3);
_

この関数makeを書くことは可能ですか?私はこれを試しましたが、GCC 4.5または4.6では機能しません:

_template <template <typename...> class TemplateClass, typename... Args>
TemplateClass<Args...> make(Args&&... args)
{
    return TemplateClass<Args...>(std::forward<Args>(args)...);
}
_

(たとえば)make<std::pair>(1, 2)を呼び出そうとすると、

_error: no matching function for call to 'make(int, int)'
_

ここのどこかで構文が間違っていますか?
それともこれは正しいですか、GCCは間違っていますか?
それとも、これはC++ 0xでは基本的に不可能ですか?

[編集]

提案 N2555 はこれが許可されていることを示唆しているようで、 GCCはGCC4.4でそれを実装したと主張している

46
Peter Alexander

そうです。私はそれが機能すると期待しています。したがって、GCCはそれを拒否することに誤りがあると思います。 FWIW:

#include <utility>

template <template <typename...> class TemplateClass, typename... Args>
TemplateClass<Args...> make(Args&&... args)
{
    return TemplateClass<Args...>(std::forward<Args>(args)...);
}

int main() {
  make<std::pair>(1, 2);
}


// [js@Host2 cpp]$ clang++ -std=c++0x main1.cpp
// [js@Host2 cpp]$

これはおそらくGCCの癖です。 devスナップショットを使用するには、次のものを入手できます(現在4.6のコピーはありません)。

template<
    template<typename...> class TemplateClass
    , typename... Args

    , typename Result = TemplateClass<Args...>
    // Also works with the arguably more correct
    // , typename Result = TemplateClass<
    //     typename std::decay<Args>::type...
    // >
>
Result
make(Args&&... args)
{ /* as before */ }
7
Luc Danton

これはまったく間違っています。たとえば、_make_shared_を考えます。 _make_shared_のポイントは、使用時に実行時の効率の節約があることです。しかし、_make<std::shared_ptr>_を使用しようとするとどうなりますか?それがうまくいくとは思わないでください。または、コンストラクタ引数の一部のみがテンプレート引数であり、残りはそうではない型についてはどうでしょうか?たとえば、make<std::vector, int>(other_vector.begin(), other_vector.end());-イテレータの型は参加しませんが、とにかくそれらを渡します。

汎用のmake関数を書くことは不可能です。

標準については、それ以降、簡単に削除できたはずです。 FDISを確認する必要があります。

3
Puppy