18

テンプレート化されたクラスまたはテンプレート化された関数 (またはその 2 つの組み合わせ) がある場合、その関数をどのようにバインドしますか (テンプレート型パラメーターを保持します)。

以下の投稿で、明示的なテンプレート型パラメーターを使用して関数にバインドするための基本的な構文について、いくつかの助けがありましたが、プロセスでテンプレート型パラメーターを提供する機能を失いました。

今後の呼び出しでテンプレート型パラメーターを提供できるように、これを機能させることは可能ですか?

このコードを大幅にクリーンアップしましたが、正しい構文が見つからないため、明らかにコンパイルされません (これを行う方法はありますか)?

これを簡素化するために「ベクトル」要件を削除しました。

助けてくれてありがとう!

#include <functional>
#include <vector>
#include <string>

/***************************************/
template <typename CommandTemplateType>
class Storage
{
  public:
   // No idea how to define this vector to allow Template Parameters
   // static std::vector<std::function<void<ParameterTemplateType>
   //     (std::shared_ptr<ParameterTemplateType>)>> Functions;

   // I really don't need the collection, a single member would kick start my research:
   static std::function<void<ParameterTemplateType>(std::shared_ptr<ParameterTemplateType>)> Function;

  template <typename ParameterTemplateType>
  static void Execute(ParameterTemplateType parameter)
  {
     // Look up index, or loop through all.. 
     // I am trying to invoke the bound function with a template param:
     // Functions[index]<ParameterTemplateType>(parameter);
     // preferably, just:  
     Function<ParameterTempalteType>(parameter); 
  }
};

/***************************************/
template <typename TemplateType>
class MyClass
{

   template <typename ParameterTemplateType>
   void MyFunction(ParameterTemplateType myParameter)
   {
     // Do something; 
   }

   MyClass()
   {
      std::string parameter = L"Test String";

      // Do not know how to include the 
      // template<typename ParameterTemplateType> definition to bind call.
      // Storage::Functions.push_back(
      //     std::bind(&MyClass::MyFunction<ParameterTemplateType>,
//        this, std::placeholders::_1));

     // Or just something like:
     Storage::Function = std::bind(&MyClass::MyFunction<ParameterTemplateType>,
                             this, std::placeholders::_1));

      /***************************************/
      // Call the bound function with an explicit parameter somehow:
      std::string parameter = L"Test String";          
      Storage::Execute<std::string>(parameter);


   }
};
4

4 に答える 4

15

重要な問題は、C++11 では次のようなことができないことです。

// Doesn't compile
template <typename TemplateType>
static std::function<void(std::shared_ptr<TemplateType>)> Function;

クラスと関数はテンプレート化できますが、メンバー プロパティはテンプレート化できません。

「魔法」は次のとおりです。

/*******************************************************************/
// Define a Function Pointer in a Container
class Storage
{
   template <typename TemplateType>
   struct FunctionContainer {
       static std::function<void(std::shared_ptr<TemplateType>)> Function;
   };
};
/*******************************************************************/
// Initialize FunctionContainer's Static Function Pointer if using static pointer.
template <typename TemplateType>
std::function<void(std::shared_ptr<TemplateType>)> Storage
    ::FunctionContainer<TemplateType>::Function;

次に、テンプレート化された関数をこの関数に次のようにバインドできます。

// Bind Function Pointer in Container to a Local Function
class MyClass
{
   template <typename TemplateType>
   void MyFunction(std::shared_ptr<TemplateType> parameter)
   {
     // Do something.
     // You can make this templated or non-templated.
   }
   MyClass()
   {
     // If you really want, you can templatize std::string in the following:
     Storage::FunctionContainer<std::string>::Function 
       = std::bind(&MyFunction<std::string>, this, std::placeholders::_1);
   }
}

そして、これらすべてを呼び出して、次のようにテンプレート化された型パラメーターを提供できます。

//Invocation
std::shared_ptr<std::string> parameter;
parameter->get() = "Hello World".
Storage::FunctionContainer<std::string>::Function(parameter);
于 2013-02-16T20:17:34.003 に答える
10

のテンプレート引数は、テンプレート型の置換が行われたstd::functionの関数のシグネチャである必要があります。あなたの場合、メンバー関数の署名にも影響しません-常に a を返し、単一の引数を取ります。したがって、次のように保存する必要があります。TemplateTypeFunctionTemplateTypeMyFunctionstd::stringstd::stringstd::functionstd::vector

static std::vector<std::function<std::string(std::string)>> Functions;

メンバー関数には暗黙的な最初の引数があることを思い出してくださいthisMyClass<...>::MyFunc<...>の最初の引数を、呼び出したいオブジェクトにバインドする必要があります。おそらく、MyClassのコンストラクターで関数をバインドしているため、オブジェクトをそのMyClassインスタンスにする必要があります。つまり、次のpush_backようになります。

Storage::Functions.push_back(
  std::bind(&MyClass<TemplateType>::MyFunction<int>, this,
    std::placeholders::_1)
);

プッシュされる関数はオブジェクトFunctionsにバインドされMyClass、 type の単一の引数を取りますstd::string。これらの関数のいずれかを次のように呼び出すことができます。

Storage::Functions[0]("something");
于 2013-02-06T12:28:44.397 に答える
5

私があなたを正しく理解していれば... :)

template<class T> void foo(T) 関数 foo<int>() と foo<double> は異なる型であり、両方の関数へのポインターを直接保持するベクトルを作成できないため、やりたいことは不可能です。ベクトルは同種のコンテナです。

これを克服するために、boost::variant<> を使用して、さまざまなタイプの関数へのポインターを格納するか、関数の引数を格納できます。

template<class T> void foo(T);
typedef boost::variant<void (*)(int), void (*)(double)> func_ptr_variant;
std::vector<func_ptr_variant> v;
v.push_back(foo<int>);
v.push_back(foo<double>);

typedef boost::variant<int, double> argument;
std::vector<void (*)(argument)) v;
v.push_back(foo);
v.push_back(bar);
// foo and bar are defined as void foo(argument a) and void bar(argument a)

残念ながら、C++ はオンザフライでコード生成を行うことができないため、いずれの場合でも関数テンプレートをコンテナーに挿入する前にインスタンス化する必要があります。関数が使用される可能性のある引数のすべてのタイプを知っている可能性があるので、問題にならない可能性があると思います。

于 2013-02-16T18:21:34.490 に答える
4

MyClassのc-torはそれについて何も知らないので、このように明示的に特殊化されたもの(申し訳ありませんが、私の用語です...正しい用語はわかりません)FunctionTemplateTypeのみをプッシュバックできます。

#include <functional>
#include <vector>
#include <string>

struct Storage
{
  // Have no idea what this signature should really be:
  static std::vector<std::function<void ()>> Functions;

};
std::vector<std::function<void ()>> Storage::Functions;

template <typename TemplateType>
class MyClass
{
   template <typename FunctionTemplateType>
   std::string MyFunction(std::string myParameter)
   {
     return "Hellö: " + myParameter;

   }
public:
   MyClass()
   {
      Storage::Functions.push_back(
          std::bind( & MyClass<TemplateType>::MyFunction<std::string>, this, "borisbn" )
//                                                       ^^^^^^^^^^^
      );
   }
};

int main() {
    MyClass<int> obj;
}

liveworkspaceリンク

于 2013-02-06T11:18:31.097 に答える