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
从未被调用。我还能如何完成这项工作?