昨日、次の例のように、非オブジェクト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
テンプレートが呼び出されない場合でも、コンパイラはすぐにエラーをトリガーするため、失敗します。他にどうすればこれを機能させることができますか?