Информация об изменениях

Сообщение Re: Передача объекта, возвращаемого функцией, в другую функц от 27.09.2019 4:36

Изменено 27.09.2019 5:01 DDDX

Re: Передача объекта, возвращаемого функцией, в другую функцию.
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Привет всем.


Тут одна мысль посетила, благодаря rg45
Автор: rg45
Дата: 26.09.19
. Но я решил с ней повременить.
  И привести нормальный пример описываемой проблемы (VS2019)
////////////////////////////////////////////////////////////////////////////////
#include <iostream>

////////////////////////////////////////////////////////////////////////////////
//class t_errors

class t_errors
{
 public:
  virtual void add(int errCode)=0;
};

////////////////////////////////////////////////////////////////////////////////
//class t_context

class t_context
{
 private:
  t_context(const t_context&)=delete;
  t_context& operator = (const t_context&)=delete;

 public:
  class tag_errs_without_limits:public t_errors
  {
   public:
    explicit tag_errs_without_limits(t_context* const pCtx):m_pCtx(pCtx){;}

    virtual void add(int errCode)override {m_pCtx->helper__add_error(errCode);}

   private:
    t_context* m_pCtx;
  };//class tag_errs_without_limits

 public:
  class tag_errs_with_limits:public t_errors
  {
   public:
    explicit tag_errs_with_limits(t_context* const pCtx):m_pCtx(pCtx){;}

    virtual void add(int errCode)override {/*check limits*/; m_pCtx->helper__add_error(errCode);}

   private:
    t_context* m_pCtx;
  };//class tag_errs_with_limits

 public:
  t_context()
  {}

  tag_errs_without_limits get_errors_without_limits()
  {
   return tag_errs_without_limits(this);
  }//get_errors_without_limits

  tag_errs_with_limits get_errors_with_limits()
  {
   return tag_errs_with_limits(this);
  }//get_errors_with_limits

 private:
  void helper__add_error(int const errCode)
  {
   std::cout<<"helper__add_error: "<<errCode<<"!\n";
  }
};

////////////////////////////////////////////////////////////////////////////////

//add_error - может быть виртуальным методом некоторого класса

void add_error(t_errors& errs,int const errCode)
{
 errs.add(errCode);
}//add_error

////////////////////////////////////////////////////////////////////////////////

int main()
{
 t_context ctx;

 add_error(ctx.get_errors_without_limits(),1);
 add_error(ctx.get_errors_with_limits(),2);

 return 0;
}//main
////////////////////////////////////////////////////////////////////////////////

  Как это сейчас модно говорить, Real World Code (RWC) выглядит так:
//...
  virtual void GetData_AddErrorRecord__CantGetData
                               (typename call_ctx_type::errors_type& Errors,
                                const TBaseColumnsInfoImpl*          pColumnsInfo,
                                const DBBINDING&                     Binding,
                                const void*                          pData,
                                HRESULT                              get_data_hr)=0;
//...
template<class TStorageTraits>
HRESULT TMemRowsetStorageROImpl<TStorageTraits>::GetData
                                    (call_ctx_type&                    CallCtx,
                                     TRowBmk                     const Bmk,
                                     const TBindingArray*        const pBindingArray,
                                     const TBaseColumnsInfoImpl* const pColumnsInfo,
                                     void*                       const pData)
{
 //....
     if(get_data_hr!=S_OK)
     {
      this->GetData_AddErrorRecord__CantGetData
       (CallCtx.ErrorsWithLimit(), //<---------------- Вот проблемная точка
        pColumnsInfo,
        *pBinding,
        pData,
        get_data_hr); //no throw

      ++cntErrors;
     }//if
 //....
}//GetData
//...

Когда Conformance Mode=Yes, пример не компилируется:
Error    C2664     'void add_error(t_errors &,const int)': cannot convert argument 1 from 't_context::tag_errs_without_limits' to 't_errors &'
Error    C2664     'void add_error(t_errors &,const int)': cannot convert argument 1 from 't_context::tag_errs_with_limits' to 't_errors &'

Как я тут уже отмечал
Автор: Коваленко Дмитрий
Дата: 26.09.19
, ошибку компиляции можно задавить с помощью *& :
 add_error(*&ctx.get_errors_without_limits(),1);
 add_error(*&ctx.get_errors_with_limits(),2);

Можно передавать add_error, чтобы он получал указатель на errs. Тоже работает:
void add_error(t_errors* errs,int const errCode);
//...
 add_error(&ctx.get_errors_without_limits(),1);
 add_error(&ctx.get_errors_with_limits(),2);
//...

Как по мне, вариант со ссылкой выглядел лучше.
Re: Передача объекта, возвращаемого функцией, в другую функц
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Привет всем.


Тут одна мысль посетила, благодаря rg45
Автор: rg45
Дата: 26.09.19
. Но я решил с ней повременить.
  И привести нормальный пример описываемой проблемы (VS2019)
////////////////////////////////////////////////////////////////////////////////
#include <iostream>

////////////////////////////////////////////////////////////////////////////////
//class t_errors

class t_errors
{
 public:
  virtual void add(int errCode)=0;
};

////////////////////////////////////////////////////////////////////////////////
//class t_context

class t_context
{
 private:
  t_context(const t_context&)=delete;
  t_context& operator = (const t_context&)=delete;

 public:
  class tag_errs_without_limits:public t_errors
  {
   public:
    explicit tag_errs_without_limits(t_context* const pCtx):m_pCtx(pCtx){;}

    virtual void add(int errCode)override {m_pCtx->helper__add_error(errCode);}

   private:
    t_context* m_pCtx;
  };//class tag_errs_without_limits

 public:
  class tag_errs_with_limits:public t_errors
  {
   public:
    explicit tag_errs_with_limits(t_context* const pCtx):m_pCtx(pCtx){;}

    virtual void add(int errCode)override {/*check limits*/; m_pCtx->helper__add_error(errCode);}

   private:
    t_context* m_pCtx;
  };//class tag_errs_with_limits

 public:
  t_context()
  {}

  tag_errs_without_limits get_errors_without_limits()
  {
   return tag_errs_without_limits(this);
  }//get_errors_without_limits

  tag_errs_with_limits get_errors_with_limits()
  {
   return tag_errs_with_limits(this);
  }//get_errors_with_limits

 private:
  void helper__add_error(int const errCode)
  {
   std::cout<<"helper__add_error: "<<errCode<<"!\n";
  }
};

////////////////////////////////////////////////////////////////////////////////

//add_error - может быть виртуальным методом некоторого класса

void add_error(t_errors& errs,int const errCode)
{
 errs.add(errCode);
}//add_error

////////////////////////////////////////////////////////////////////////////////

int main()
{
 t_context ctx;

 add_error(ctx.get_errors_without_limits(),1);
 add_error(ctx.get_errors_with_limits(),2);

 return 0;
}//main
////////////////////////////////////////////////////////////////////////////////

  Как это сейчас модно говорить, Real World Code (RWC) выглядит так:
//...
  virtual void GetData_AddErrorRecord__CantGetData
                               (typename call_ctx_type::errors_type& Errors,
                                const TBaseColumnsInfoImpl*          pColumnsInfo,
                                const DBBINDING&                     Binding,
                                const void*                          pData,
                                HRESULT                              get_data_hr)=0;
//...
template<class TStorageTraits>
HRESULT TMemRowsetStorageROImpl<TStorageTraits>::GetData
                                    (call_ctx_type&                    CallCtx,
                                     TRowBmk                     const Bmk,
                                     const TBindingArray*        const pBindingArray,
                                     const TBaseColumnsInfoImpl* const pColumnsInfo,
                                     void*                       const pData)
{
 //....
     if(get_data_hr!=S_OK)
     {
      this->GetData_AddErrorRecord__CantGetData
       (CallCtx.ErrorsWithLimit(), //<---------------- Вот проблемная точка
        pColumnsInfo,
        *pBinding,
        pData,
        get_data_hr); //no throw

      ++cntErrors;
     }//if
 //....
}//GetData
//...

Когда Conformance Mode=Yes, пример не компилируется:
Error    C2664     'void add_error(t_errors &,const int)': cannot convert argument 1 from 't_context::tag_errs_without_limits' to 't_errors &'
Error    C2664     'void add_error(t_errors &,const int)': cannot convert argument 1 from 't_context::tag_errs_with_limits' to 't_errors &'

Как я тут уже отмечал
Автор: Коваленко Дмитрий
Дата: 26.09.19
, ошибку компиляции можно задавить с помощью *&. Но вылезут предупреждения 4-го уровня:
 add_error(*&ctx.get_errors_without_limits(),1); //warning C4238:  nonstandard extension used: class rvalue used as lvalue
 add_error(*&ctx.get_errors_with_limits(),2); //warning C4238:  nonstandard extension used: class rvalue used as lvalue

Можно переделать add_error, чтобы он получал указатель на errs. Тоже компилируется с предупреждениями 4-го уровня:
void add_error(t_errors* errs,int const errCode);
//...
 add_error(&ctx.get_errors_without_limits(),1); //warning C4238:  nonstandard extension used: class rvalue used as lvalue
 add_error(&ctx.get_errors_with_limits(),2); //warning C4238:  nonstandard extension used: class rvalue used as lvalue
//...


Как по мне, начальный вариант со ссылкой выглядел лучше.