diff --git a/src/V3Dfg.h b/src/V3Dfg.h index 429926703..df6a0f1c5 100644 --- a/src/V3Dfg.h +++ b/src/V3Dfg.h @@ -247,7 +247,10 @@ public: // Calls given function 'f' for each source vertex of this vertex. If 'f' // returns true, further sources are not iterated and this method returns // true itself. Unconnected source edges are not iterated. - bool foreachSource(std::function f) { + template + bool foreachSource(T_Callable&& f) { + static_assert(vlstd::is_invocable_r::value, + "T_Callable 'f' must have a signature compatible with 'bool(DfgVertex&)'"); for (const std::unique_ptr& edgep : m_inputps) { if (DfgVertex* const srcp = edgep->srcp()) { if (f(*srcp)) return true; @@ -259,9 +262,13 @@ public: // Calls given function 'f' for each source vertex of this vertex. If 'f' // returns true, further sources are not iterated and this method returns // true itself. Unconnected source edges are not iterated. - bool foreachSource(std::function f) const { + template + bool foreachSource(T_Callable&& f) const { + static_assert( + vlstd::is_invocable_r::value, + "T_Callable 'f' must have a signature compatible with 'bool(const DfgVertex&)'"); for (const std::unique_ptr& edgep : m_inputps) { - if (DfgVertex* const srcp = edgep->srcp()) { + if (const DfgVertex* const srcp = edgep->srcp()) { if (f(*srcp)) return true; } } @@ -272,7 +279,10 @@ public: // returns true, further sinks are not iterated and this method returns // true itself. Unlinking/deleting the given sink during iteration is safe, // but not other sinks of this vertex. - bool foreachSink(std::function f) { + template + bool foreachSink(T_Callable&& f) { + static_assert(vlstd::is_invocable_r::value, + "T_Callable 'f' must have a signature compatible with 'bool(DfgVertex&)'"); for (const DfgEdge* const edgep : m_sinks.unlinkable()) { if (f(*edgep->dstp())) return true; } @@ -282,7 +292,11 @@ public: // Calls given function 'f' for each sink vertex of this vertex. If 'f' // returns true, further sinks are not iterated and this method returns // true itself. - bool foreachSink(std::function f) const { + template + bool foreachSink(T_Callable&& f) const { + static_assert( + vlstd::is_invocable_r::value, + "T_Callable 'f' must have a signature compatible with 'bool(const DfgVertex&)'"); for (const DfgEdge& edge : m_sinks) { if (f(*edge.dstp())) return true; } diff --git a/src/V3DfgVertices.h b/src/V3DfgVertices.h index 960d4aedd..bc2ded35d 100644 --- a/src/V3DfgVertices.h +++ b/src/V3DfgVertices.h @@ -485,28 +485,47 @@ public: return vtxp; } - bool foreachDriver(std::function f) { + template ::value, // + int> + = 0> + bool foreachDriver(T_Callable&& f) { const size_t n = nInputs(); for (size_t i = 0; i < n; ++i) { if (f(*inputp(i), m_driverData[i].m_lo, m_driverData[i].m_flp)) return true; } return false; } - bool foreachDriver(std::function f) const { + template ::value, + int> + = 0> + bool foreachDriver(T_Callable&& f) const { const size_t n = nInputs(); for (size_t i = 0; i < n; ++i) { if (f(*inputp(i), m_driverData[i].m_lo, m_driverData[i].m_flp)) return true; } return false; } - bool foreachDriver(std::function f) { + template < + typename T_Callable, + std::enable_if_t::value, // + int> + = 0> + bool foreachDriver(T_Callable&& f) { const size_t n = nInputs(); for (size_t i = 0; i < n; ++i) { if (f(*inputp(i), m_driverData[i].m_lo)) return true; } return false; } - bool foreachDriver(std::function f) const { + template ::value, int> + = 0> + bool foreachDriver(T_Callable&& f) const { const size_t n = nInputs(); for (size_t i = 0; i < n; ++i) { if (f(*inputp(i), m_driverData[i].m_lo)) return true;