2

テンプレート クラス (TC) 内でフリー テンプレート関数 (FTF) をインスタンス化する必要があります。FTF は、TC のテンプレート パラメータの 1 つをテンプレート パラメータとして使用します。TC はこれらの FTF への汎用ポインターも保持しており、これらの関数はポインターを介して呼び出されます。

FTF へのポインターを取得する手順ではインスタンス化するのに十分ではなく、GCC ツールチェーンからリンカー エラーが発生します。MSDN は FTF 仕様をそのように示していますが、FTF のインスタンスは TC のテンプレート パラメーターに依存しているため、FTF のインスタンス化をフリー スコープに配置することはできません。

これは可能ですか?いくつかの基本的な生成コードを添付しています。問題は、のコンストラクターにありclass test_serviceます。ここで、フリー関数のポインターをカスタム コンテナーに割り当てます。フリー関数が見つからない (インスタンス化されていない) というリンカ エラーが表示されます。クラスのどこかでテンプレート関数への呼び出しを指定するとインスタンス化が生成されることはわかっていますが、ポインターを介してのみ呼び出しを行います。

#include "rpc_common.h"
#include <boost/cstdint.hpp>

namespace rubble { namespace rpc {

  struct test_service_dummy_tag{};

  template<typename T>
  class test_service_skel
  {
  public:
    bool Init() {}
    bool TearDown() {}
    bool test_one(TestRequest,TestResponse){};
  private:
  };

  template<typename T_IMPL>
  bool test_service_test_one(T_IMPL & impl,ClientRequest & request)
  {
    return 0;
  }

  template<typename T_IMPL=test_service_skel<test_service_dummy_tag> >
  class test_service
  {
  public:
    test_service()
    {
      // uncomment the following two lines and a instantiation will occur.
      // ClientRequest cr;
      //test_service_test_one<T_IMPL>(m_impl,cr);
      m_dispatch_table.SetEntry( Oid("test_one",0),(void *)  & test_service_test_one<T_IMPL>);
    }
    bool Init() { return m_impl.Init(); };
    bool TearDown() { return m_impl.TearDown(); };
  private:
    T_IMPL m_impl;
    OidContainer<Oid,void *> m_dispatch_table;
  };


} }

編集: 自己完結型の最小バージョン

 class test_skel
    {
      bool test_function()
      {
        return true;
      }
    };


    template<typename T>
    bool test_function()
    {

    }

    template<typename T = test_skel>
    class test
    {
    public:
      test()
      {
        dispatch = (void *) & test_function<T>;
      }
      void * dispatch;
    };

    int main()
    {
      test<> t;
      return 0;
    }
4

2 に答える 2

2

を使用しなくても問題ありません。例void*: http://www.ideone.com/eRgUG

ただし、ポインターを a に格納することを主張するvoid*場合は、最初に特定の関数ポインターを使用してアドレスを取得し、次にキャストする必要があります-たとえば

    bool (*temp)() = &test_function<T>;
    dispatch = reinterpret_cast<void*>(temp); // YUCK

これにより、アドレスを生成するのに十分なコンテキストがコンパイラに与えられます。

ああ-DeadMGの答えを見たところ、生成する関数void*はよりきれいです...

于 2011-07-07T11:52:50.727 に答える
1

MSVCでオーバーロードが行われていない場合、自己完結型の例は、オーバーロードされた関数に関する奇妙なエラーでコンパイルされません。しかし、私はそれを回避することができました。

class test_skel
{
    bool test_function()
    {
        return true;
    }
};

template<typename T> void* to_void_pointer(T t) {
    return reinterpret_cast<void*>(t);
}

template<typename T>
bool test_function()
{
    return true;
}

template<typename T = test_skel>
class test
{
public:
    test()
    {
        dispatch = to_void_pointer(&test_function<T>);
    }
    void * dispatch;
};

int main()
{
    test<> t;
    return 0;
}

これはきれいにコンパイルされます。あなたが見ている動作と私が見た動作は、コンパイラ エラーであると思われます。

于 2011-07-07T11:52:56.367 に答える