Compile errors with moc and an (unused) header with variadic templates
-
Hi! Did I understand this correctly that you have a template class that inherits from QObject?
-
Hi! Did I understand this correctly that you have a template class that inherits from QObject?
@Wieland Nope, the class isn't even used (yet). Just included. It's used in other places in the codebase without problems.
-
@Wieland Nope, the class isn't even used (yet). Just included. It's used in other places in the codebase without problems.
Can you show us that header?
-
Can you show us that header?
@Wieland Sure. This class is covered by unit tests and also used in other places in the code, so it should be fine. It's just as soon as I merely include it in something that has a Q_OBJECT it fails.
#pragma once namespace aeon { namespace utility { template<class... Args> using signal_func = std::function<void(Args...)>; template<class... Args> class signal_connection { public: signal_connection() : handle_(0) { } explicit signal_connection(int handle, signal_func<Args...> func) : handle_(handle) , func_(func) { } int get_handle() const { return handle_; } void emit(Args...args) { func_(args...); } private: int handle_; signal_func<Args...> func_; }; template<class... Args> class signal { public: signal() = default; ~signal() = default; signal_connection<Args...> operator+=(signal_func<Args...> f) { return connect(f); } signal_connection<Args...> connect(signal_func<Args...> f) { auto connection = signal_connection<Args...>(++last_handle_, f); connections_.push_back(connection); return connection; } void disconnect(signal_connection<Args...> c) { connections_.remove_if([&c](const signal_connection<Args...> &other) { return other.get_handle() == c.get_handle(); }); } void operator()(Args...args) { for (auto c : connections_) { c.emit(args...); } } private: int last_handle_ = 0; std::list<signal_connection<Args...>> connections_; }; template<class... Args> class signal_mt { using mutex_type = std::mutex; using handle_type = std::atomic<int>; using list_type = std::list<signal_connection<Args...>>; public: signal_mt() = default; ~signal_mt() { /* \note This does not solve the 'destruction' while signal is executing problem. * Reasoning: * Thread a is the owner (he creates and destroys) and thread b executes the signal multiple times. Then * while the signal is being destroyed from thread a, thread b tries to execute the signal. Thread a will * acquire the mutex and execute the signal destructor. When the signal is destroyed it will release the * mutex and allow thread b to execute the signal that does not exist. Which will result in havoc. */ std::lock_guard<mutex_type> guard(lock_); connections_.clear(); } signal_connection<Args...> operator+=(signal_func<Args...> f) { return connect(f); } signal_connection<Args...> connect(signal_func<Args...> f) { auto connection = signal_connection<Args...>(++last_handle_, f); { std::lock_guard<mutex_type> guard(lock_); connections_.emplace_back(connection); } return connection; } void disconnect(signal_connection<Args...> c) { std::lock_guard<mutex_type> guard(lock_); connections_.remove_if([&c](const signal_connection<Args...> &other) { return other.get_handle() == c.get_handle(); }); } void operator()(Args...args) { std::lock_guard<mutex_type> guard(lock_); for (auto &c : connections_) c.emit(args...); } private: handle_type last_handle_{ 0 }; list_type connections_; mutex_type lock_; }; } // namespace utility } // namespace aeon
-
That's the problem:
void emit(Args...args)
{
func_(args...);
}You can't have a function named "emit" because that's a special keyword for the MOC. Simply rename it to something else.
-
Ah! Hmm.. I'd have to see if I can get away with renaming it. But if this works it'd be a great help thanks. I'll come back to you to let you know if that worked.
-
Great that has indeed worked.
-
Great that has indeed worked.
@RobinDegen Great :)
-
Yes. It's a macro that expands to nothing. There are couple more of these: signals and slots. If they cause trouble you can disable them and use even uglier (but not clashing) macros like Q_EMIT.
-
Yes. It's a macro that expands to nothing. There are couple more of these: signals and slots. If they cause trouble you can disable them and use even uglier (but not clashing) macros like Q_EMIT.
@Chris-Kawa Oh thanks for that. That might actually be a much better solution for us.