1

昨日、次の例のように、非オブジェクトconstからメンバー関数を呼び出すことによって引き起こされるコンパイル時エラーを理解するのに何年もかかりました:const

// my utility header
template<typename derived>
struct crtp_task : task
{
  std::list<task*> list;

  // note: cannot be const, as task::allocate_child() isn't
  template<typename... Args>      
  void add_child(Args&&... args)
  {
    list.push_back(new(task::allocate_child())
                   derived(std::forward<Args>(args)...));
  }
  /* ... */
};

// an application
struct my_task : crtp_task<my_task>
{
  some_data data;
  /* ... */
  my_task(some_data d) data(d) {}
  void generate_children() const    // constant member
  {
    /* ... */
    some_data child_data = /* ... */;
    this->add_child(child_data);    // error: cannot call non-const member
  }
};

clang のエラー メッセージは数行あり、難解すぎました ( については触れていませんconst) が、gcc はより適切なエラーを表示しました (さらに多くの行がありましたが、最終的には cv 修飾子を無視していると不平を言いました)。

したがって、将来このようなことを避けるためstatic_assert()に、ユーティリティヘッダーで使用することを考えました。私の素朴なアプローチ

// my utility header
template<typename derived>
struct crtp_task : task
{
  std::list<task*> list;

  // note: cannot be const, as task::allocate_child() isn't
  template<typename... Args>      
  void add_child(Args&&... args)
  {
    list.push_back(new(task::allocate_child())
                   derived(std::forward<Args>(args)...));
  }

  // note: catch call from const objects
  template<typename... Args>      
  void add_child(Args&&...) const
  {
    static_assert(false,"add_child() const called");
  }      
  /* ... */
};

void add_child() constテンプレートが呼び出されない場合でも、コンパイラはすぐにエラーをトリガーするため、失敗します。他にどうすればこれを機能させることができますか?

4

2 に答える 2