создание экземпляра бесплатной функции шаблона внутри класса шаблона - PullRequest
2 голосов
/ 07 июля 2011

Мне нужно создать бесплатную функцию шаблона (FTF) внутри класса шаблона (TC). FTF принимает в качестве параметра шаблона один из параметров шаблона TC. 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;
    }

Ответы [ 2 ]

2 голосов
/ 07 июля 2011

Нет проблем, если вы не используете void*, т.е.: http://www.ideone.com/eRgUG

Однако, если вы настаиваете на сохранении указателя в void*, вам нужно сначала взять адрес, используя указатель определенной функции, а затем привести - например,

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

Это дает компилятору достаточно контекста для генерации адреса для вас.

Ааа - только что увидел ответ DeadMG, функция для генерации void* более точная ...

1 голос
/ 07 июля 2011

Ваш автономный пример не скомпилируется для меня со странной ошибкой в ​​отношении перегруженных функций, когда перегрузка не происходит, с 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;
}

Это компилируется чисто.Я подозреваю, что любое поведение, которое вы видите, и которое я видел, является ошибкой компилятора.

...