2016-08-27 6 views
12

Я реализую свой собственный signal/slot (шаблон наблюдателя, стиль Qt), поэтому у меня может быть property, который уведомляет ... материал ... который был изменен.Реализация сигналов (шаблон наблюдателя): возможно изменение или const_cast?

Я думаю, что C++ 11 обеспечивает все необходимое, чтобы сделать очень сукцину и возможность использования. «Проблема», с которой я столкнулся, - это если я хочу «подключиться» к сигналу объекта const, мне нужно, чтобы функция signal::connect была константой, но изменила список обратных вызовов/наблюдателей. Есть два способа прямолинейные, чтобы исправить это:

  1. const_cast списки внутри connect.
  2. Составьте список mutable.

И мне кажется, как одно и то же (и это было предложено ранее, например в this question), и прекрасно логически, но стилистически сомнительна. Отсюда вопрос. Есть ли способ обойти это или это действительно оправданное использование const_cast/mutable?

Некоторые prelimenary код, как я сейчас:

template<typename... ArgTypes> 
class signal 
{ 
public: 
    template<typename Callable> 
    void connect(Callable&& callback) const 
    { 
    std::lock_guard<std::mutex> lock(slots_mutex); 
    slots.emplace_back(callback); 
    } 

    void emit(ArgTypes... arguments) const 
    { 
    std::lock_guard<std::mutex> lock(slots_mutex); 
    for(auto&& callback : slots) 
    { 
     callback(arguments...); 
    } 
    } 

private: 
    // mutable here allows to connect to a const object's signals 
    mutable std::vector<std::function<void(ArgTypes...)>> slots; 
    std::mutex slots_mutex; 

}; 

Примечание Я не проверял этот код; это всего лишь отражение моего нынешнего состояния ума.

+2

Неисследованный код ... tsk tsk ... –

+0

@Arnav Я буквально пишу тесты сейчас, мне просто нужно было снять эту проблему с дизайном: p. – rubenvb

+0

Боюсь, я не понимаю, почему сам 'signal' должен выставлять методы' const'. Почему бы не позволить пользователю «сигнала» решить, хотят ли они его изменять (или нет)? –

ответ

9

mutable обычно лучший выбор для таких случаев.

Избегайте (const) отливка всякий раз, когда вы можете, это склонным для поражения неопределенного поведения, в то время как mutable гарантирована не 1).


mutable члены класса гарантированно не идти в испущенных кодов .text сегмент, например.

2

Есть два прямолинейные способа исправить это:

  1. const_cast списки внутри connect.
  2. Составьте список mutable.

На самом деле есть третий выбор (который является общей целью потенциальных обходной путь, был C++ не предоставил mutable ключевое слово) - вы можете переместить заинтересованные данные из синтаксического объекта:

class X 
{ 
    mutable int   i1_; 

    // Data pointed to by i2_ semantically belongs to this object 
    // but doesn't constitute a syntactical part of it so it is not 
    // subject to const-correctness checks by the compiler. 
    std::unique_ptr<int> i2_; 

public: 
    void constFunc() const { 
     i1_ = 123; 
     *i2_ = 456; 
    } 
}; 

Несмотря на наличие этой дополнительной опции, я по-прежнему согласен с πάντα ῥεῖanswer, что ключевое слово mutable является правильным выбором для таких случаев. Он явно документирует стандартным образом (например, позволяет быть grepped), что концептуально операции const этого класса могут быть технически не мутирующими.Это полезно знать, например, когда речь идет о безопасности потоков const функций класса.

0

сигнал: изменяет сигнал: слот. Итак, я думаю, что единственное, что вам нужно сделать, это изменить свой дизайн. Пусть сигнал :: connect be mutable и callers hold mutable signal указатели.

 Смежные вопросы

  • Нет связанных вопросов^_^