Ошибки, баги, вопросы - страница 2660

Баг МТ5 (build 2342) возникает ошибка компиляции при генерации кода шаблонной функции несмотря на то, что имеется перегруженная шаблонная функция с подходящей сигнатурой для передаваемых параметров.
С++ online: https://onlinegdb.com/HyxjmV-DVI

#ifdef __cplusplus
    #include <iostream>
#endif


class C{
public:
   struct A{
      char aaa;
   };
   
   template<typename T>
   void test(A&, T&, T&, void* = NULL){
      printf("1");
   }
   
   template<typename T>
   void test(T&, T&, T&){
      printf("2");
   }
};

struct B : public C::A{
   char data;
};

struct D{
   char data;
};


void OnStart(){
   C c;

   B b;
   D d;
   
   c.test(b, b, b);    // should be: 2       
   c.test(b, d, d);    // should be: 1       //Compile Error: template parameter ambiguous, could be 'B' or 'D'
}

int main(){
   OnStart();
   return 0;
}
Sergey Dzyublik :

Баг МТ5 (build 2342) возникает ошибка компиляции при генерации кода шаблонной функции несмотря на то, что имеется перегруженная шаблонная функция с подходящей сигнатурой для передаваемых параметров.
С++ online:  https://onlinegdb.com/HyxjmV-DVI

Вы когда-нибудь получали ответ от Metaquotes о всей этой тяжелой тестовой работе, которую вы выполняете?
Не знал о такой возможности, спасибо.
Alain Verleyen:
Вы когда-нибудь получали ответ от Metaquotes о всей этой тяжелой тестовой работе, которую вы выполняете?

И да, и нет.
С моей стороны претензий нет, но хорошее слово ни когда не помешает.

Ни как не получается решить следующую задачу:
Как получить "частичную специализацию" для функции test, что бы различать передаваемые параметры и выполнить в каждом из случаем свой алгоритм?
Буду рад помощи, спасибо.

С++ online c ожидаемым поведением (https://onlinegdb.com/rycNVNDN8).
class C{
public:
   struct A{
   public:
      char aaa;
      
      A (char value = 0) : aaa(value){}
      void set(char value){
         aaa = value; 
      };
      char get(){return aaa;}
   };
   
   void test(A&, A& a1, A& a2){
      printf("1");
      a1.aaa = a2.aaa;
   }
   
   template<typename T>
   void test(A&, T& d1, T& d2){
      printf("2");
      d1.set(d2.get());
   }
};

struct B : public C::A{};


struct D{
private:
   char data;
public:  
   D(char value = 0) : data(value){}
   void set(char value){
      data = value; 
   };
   char get(){return data;}
};


void OnStart(){
   C c;

   B b;
   D d;
   
   c.test(b, b, b);    // 2      should be: 1
   c.test(b, d, d);    // 2      should be: 2   
}
Sergey Dzyublik:
Ни как не получается решить следующую задачу:
Как получить "частичную специализацию" для функции test, что бы различать передаваемые параметры и выполнить в каждом из случаем свой алгоритм?
Буду рад помощи, спасибо.
class C{
public:
   struct A{
      char aaa;
   };
   
   /*void test(A&, A&, A&){
      printf("1");
   }*/
   
   template<typename T>
   void test(A&, T&, T&){
      if (sizeof(T)==sizeof(A)) printf("1");
      else                      printf("2");
   }
};

struct B : public C::A{
   char data;
};

struct D{
   char data;
};


void OnStart(){
   C c;

   B b;
   D d;
   
   c.test(b, b, b);    // 2      should be: 2 
   c.test(b, d, d);    // 1      should be: 1    
}
Nikolai Semko:

Прошу прощение, что упростил код до минимального, вводя этим определенные неточности, в частности:
- передаваемые в функцию объекты имеют одинаковый размер (код обновлен);
- вместо тупого вывода printf("1");/printf("2"); в действительности выполняется доступ к интерфейсу или к внутренностям объекта напрямую, это в свою очередь не дает возможность инлайнить два алгоритма в единую функцию вызова (код обновлен).

Sergey Dzyublik:

Прошу прощение, что упростил код до минимального, вводя этим определенные неточности, в частности:
- передаваемые в функцию объекты имеют одинаковый размер (код обновлен);
- вместо тупого вывода printf("1");/printf("2"); в действительности выполняется доступ к интерфейсу или к внутренностям объекта напрямую, это в свою очередь не дает возможность инлайнить два алгоритма в единую функцию вызова (код обновлен).

class C{
public:
   struct A{
   public:
      char aaa;
      
      A (char value = 0) : aaa(value){}
      void set(char value){
         aaa = value; 
      };
      uint Type(){return 0x778F6712;}
      char get(){return aaa;}
      A Get() {return this;}
   };
   
   void test(A&, A& a1, A& a2){
      printf("1");
      a1.aaa = a2.aaa;
   }
   
   template<typename T>
   void test(A& a, T& d1, T& d2){
      if (a.Type()== d1.Type()) test(a,d1.Get(),d2.Get());
      else {
      printf("2");
      d1.set(d2.get());}
   }
};

struct B : public C::A{};


struct D{
private:
   char data;
public:  
   D(char value = 0) : data(value){}
   void set(char value){
      data = value; 
   };
   uint Type(){return 0x308FD7FE;}
   char get(){return data;}
   D Get() {return this;}
};


void OnStart(){
   C c;

   B b;
   D d;
   
   c.test(b, b, b);    // 1      should be: 1
   c.test(b, d, d);    // 2      should be: 2   
}


ну или так:

class C{
public:
   struct A{
   public:
      char aaa;
      
      A (char value = 0) : aaa(value){}
      void set(char value){
         aaa = value; 
      };
      char get(){return aaa;}
      A Get() {return this;}
   };
   
   void test(A&, A& a1, A& a2){
      printf("1");
      a1.aaa = a2.aaa;
   }
   
   template<typename T>
   void test(A& a, T& d1, T& d2){
      printf("2");
      d1.set(d2.get());
   }
};

struct B : public C::A{};


struct D{
private:
   char data;
public:  
   D(char value = 0) : data(value){}
   void set(char value){
      data = value; 
   };
   char get(){return data;}
   D Get() {return this;}
};


void OnStart(){
   C c;

   B b;
   D d;
   
   c.test(b.Get(), b.Get(), b.Get());    // 1      should be: 1
   c.test(b.Get(), d.Get(), d.Get());    // 2      should be: 2   
}
Спасибо за вариант решения,
он не идеальный, так как требует изменений в структуре используемых объектов и размазывает логику, зато работает.

И да, лучше сделать функцию-обертку над test:
   template<typename T>
   void test(A& a, T& t1, T& t2){ 
      __test(a, t1.CastToMain(), t2.CastToMain());
   }
Чем искать по проекту все вызовы:
   c.test(b, b.CastToMain(), b.CastToMain());    // 1      should be: 1
   c.test(b, d.CastToMain(), d.CastToMain());    // 2      should be: 2  
В любом случае - спасибо большое за помощь.
Sergey Dzyublik:
Спасибо за вариант решения,
он не идеальный, так как требует изменений в структуре используемых объектов и размазывает логику, зато работает.

И да, лучше сделать функцию-обертку над test:
Чем искать по проекту все вызовы:

В любом случае - спасибо большое за помощь.

да, согласен