C вопросы относительно ошибки переопределения при реализации шаблона статической функции-члена?

#c

#c

Вопрос:

Я пытаюсь реализовать статическую функцию в исходном файле cpp. Получить ошибку переопределения. Может кто-нибудь мне помочь? Большое спасибо!

 DEFINE_MY_STATIC_PTR(B_type)
DEFINE_MY_STATIC_PTR(A_type)
  

— ошибка: переопределение

 struct A_type : B_type
{}

#define DEFINE_MY_STATIC_PTR( TYPE )
  template< typename TYPE > 
  My_self_deleting* My_static_ptr<TYPE>::my_self_deleting_ptr( TYPE* ptr ) 
  {  return ptr; } 

template<typename TYPE> 
struct My_static_ptr : My_pointer 
{
    static My_self_deleting*    my_self_deleting_ptr   ( TYPE* );
}
  

Как правильно выполнить такое определение?

Из всей справки я обнаружил, что он должен удалить приведенный выше шаблон. При использовании это станет реализацией для каждого типа.

 #define DEFINE_MY_STATIC_PTR( TYPE )
  My_self_deleting* My_static_ptr<TYPE>::my_self_deleting_ptr( TYPE* ptr ) 
  {  return ptr; } 

DEFINE_MY_STATIC_PTR(B_type)
          error: too few template-parameter-lists
  

Должен ли я добавить что-то еще к этому определению макроса?

Да, добавить шаблон <>

   #define DEFINE_MY_STATIC_PTR( TYPE )
  template <>
  My_self_deleting* My_static_ptr<TYPE>::my_self_deleting_ptr( TYPE* ptr ) 
  {  return ptr; } 
  

Комментарии:

1. вы уверены, что поняли механизм шаблона?

2. Какова цель этого макроса? Почему бы вам просто не использовать шаблоны так, как они предназначены?

3. Я учусь писать код с шаблоном, и этот код — это то, что я вижу из другой библиотеки. Я думаю, это просто. Создает ли этот макрос проблемы с получением этой ошибки?

4. Мы не можем сказать вам, «как правильно выполнить такое определение», если вы не скажете нам, чего вы пытаетесь достичь.

5. определение DEFINE_MY_STATIC_PTR по-прежнему включает переопределение оператора, например : ::operate= и т. Д. Итак, чтобы избежать дублирования этого кода везде с разницей только в типах. Макрос предназначен для этой цели.

Ответ №1:

Я не совсем уверен, что вы пытаетесь сделать, но позвольте мне сделать несколько общих замечаний:

У вас нет класса, у вас есть шаблон класса. Это означает, что вы обычно не можете отделить реализацию от определения, поскольку определение должно быть видно в каждой точке, где вы создаете экземпляр шаблона. Таким образом, типичным решением было бы поместить все в заголовок:

 // header.hpp
template<typename T> 
struct My_static_ptr : My_pointer 
{
  static My_self_deleting * my_self_deleting_ptr(T * p)
  {
     return p;
  }
};
  

Только в определенных особых ситуациях вы могли бы рассмотреть альтернативу предоставления ограниченного набора явных экземпляров шаблонов:

 // header.hpp
template<typename T> 
struct My_static_ptr : My_pointer 
{
  static My_self_deleting * my_self_deleting_ptr(T * p);
};
  

 // implementation.cpp
template<typename T> My_self_deleting * My_static_ptr<T>::my_self_deleting_ptr(T * p)
{
  return p;
}
// Only the following specializations are usable in your entire program!
template struct My_static_ptr<int>;
template struct My_static_ptr<double>;
template struct My_static_ptr<Foo>;
  

Ответ №2:

В принципе, механизм шаблонов можно использовать, чтобы избежать перезаписи одного и того же алгоритма для разных типов.
Добавление макроса для объявления нескольких шаблонов приводит к переопределению шаблона.

В вашем случае достаточно единственного объявления метода шаблона. Вот как должен выглядеть ваш код:

 // declaration of struct A_type
struct A_type : B_type
{}

// declaration of template class My_static_ptr, of template parameter TYPE
template<typename TYPE> 
struct My_static_ptr : My_pointer 
{
    // declaration of template method my_self_deleting_ptr, of template parameter TYPE
    static My_self_deleting*    my_self_deleting_ptr   ( TYPE* );
}

// definition of template static method my_self_deleting_ptr, of template parameter TYPE
template< typename TYPE >
My_self_deleting* My_static_ptr<TYPE>::my_self_deleting_ptr( TYPE* ptr ) 
{  return ptr; } 
  

Затем вам нужно создать экземпляр вашего шаблона с конкретным типом, чтобы вы могли его использовать:

 // instantiation of the template for A_type, by creating an object My_static_ptr parameterized with A_type
My_static_ptr< A_type > myStaticPointer_of_A_type;
  

Комментарии:

1. Большое спасибо всем, кто выше, за попытку ответить на мой вопрос.

Ответ №3:

Чтобы уточнить, почему эта конкретная ошибка, когда компилятор видит (ну, в данном случае препроцессор):

 DEFINE_MY_STATIC_PTR(B_type)
DEFINE_MY_STATIC_PTR(A_type)
  

Он применяет макрос и выполняет текстовую замену аргументов макроса, заканчивающуюся:

 template< typename B_type >
  My_self_deleting* My_static_ptr<B_type>::my_self_deleting_ptr( B_type* ptr )
  {  return ptr; } 

template< typename A_type >
  My_self_deleting* My_static_ptr<A_type>::my_self_deleting_ptr( A_type* ptr )
  {  return ptr; }
  

Хотя для вас A_type и B_type , вероятно, означают типы с таким именем, для компилятора они являются просто идентификаторами как T или U . Таким образом, этот код в точности эквивалентен:

 template< typename T >
  My_self_deleting* My_static_ptr<T>::my_self_deleting_ptr( T* ptr )
  {  return ptr; } 

template< typename T >
  My_self_deleting* My_static_ptr<T>::my_self_deleting_ptr( T* ptr )
  {  return ptr; } 
  

И там у вас есть несколько определений: Вы дважды определили my_self_deleting_ptr функцию-член шаблона класса в одной и той же единице перевода, что является ошибкой, даже если оба определения в точности эквивалентны.

Комментарии:

1. Большое спасибо за то, что вы помогли мне с этим делом. Все это дало мне хорошую базу знаний, чтобы разобраться в этом. Этот фрагмент кода взят из сторонней библиотеки и должен передаваться со старым компилятором gcc. Если я закомментирую одно из определений, это даст мне неопределенную неопределенную ссылку на ошибку ссылки `MY_Class::My_static_ptr<My_Class:: A_type>::operator= (MY_Class:: A_type *)’ со ссылкой. Все еще посмотрите на код и дадим более подробную информацию.