4040// ==============================================================================
4141
4242#ifdef STONEYDSP_DEBUG
43- #include < iostream>
44- #define DBG (msg, ...) do { ::std::cerr << std::string (msg, ##__VA_ARGS__) << std::endl; } while (0 )
43+ #include < iostream>
44+ #define DBG (msg, ...) do { ::std::cerr << std::string (msg, ##__VA_ARGS__) << std::endl; } while (0 )
4545#else
46- #define DBG (msg, ...) ::StoneyDSP::ignoreUnused(msg, ##__VA_ARGS__)
46+ #define DBG (msg, ...) ::StoneyDSP::ignoreUnused(msg, ##__VA_ARGS__)
47+ #endif
48+
49+ #ifdef STONEYDSP_DEBUG
50+ #define assert_message (condition, message ) assert ((condition) && (message))
51+ #else
52+ #define assert_message (condition, message ) ::StoneyDSP::ignoreUnused(condition, message)
4753#endif
4854
4955// #if defined (STONEYDSP_DEBUG)
@@ -152,6 +158,7 @@ ::StoneyDSP::StoneyVCV::Engine<T>::~Engine() noexcept
152158 DBG (" Destroying StoneyDSP::StoneyVCV::Engine" );
153159}
154160
161+ // Explicit instantiations to ensure the definition is visible to the linker...
155162template struct ::StoneyDSP::StoneyVCV::Engine<double >;
156163template struct ::StoneyDSP::StoneyVCV::Engine<float >;
157164
@@ -167,10 +174,16 @@ template struct ::StoneyDSP::StoneyVCV::Engine<float>;
167174template <class TWidget = ::rack::widget::Widget>
168175inline TWidget *createWidget (::rack::math::Vec pos)
169176{
177+ static_assert (::std::is_base_of<::rack::widget::Widget, TWidget>::value, " TWidget must be derived from rack::widget::Widget" );
178+
170179 TWidget *o = new TWidget;
171180 o->box .pos = pos;
172181 return o;
173182}
183+ // Explicit instantiations to ensure the definition is visible to the linker...
184+ template ::rack::widget::Widget *::StoneyDSP::StoneyVCV::createWidget<::rack::widget::Widget>(::rack::math::Vec pos);
185+
186+ // ==============================================================================
174187
175188/* *
176189 * @brief Creates a `Widget` subclass with its center at a position.
@@ -186,6 +199,10 @@ inline TWidget *createWidgetCentered(::rack::math::Vec pos)
186199 o->box .pos = o->box .pos .minus (o->box .size .div (2 ));
187200 return o;
188201}
202+ // Explicit instantiations to ensure the definition is visible to the linker...
203+ template ::rack::widget::Widget *::StoneyDSP::StoneyVCV::createWidgetCentered<::rack::widget::Widget>(::rack::math::Vec pos);
204+
205+ // ==============================================================================
189206
190207/* *
191208 * @brief Creates a `Widget` subclass with its top-left at a position and its
@@ -203,6 +220,10 @@ inline TWidget *createWidgetSized(::rack::math::Vec pos, ::rack::math::Vec size)
203220 o->box .size = size;
204221 return o;
205222}
223+ // Explicit instantiations to ensure the definition is visible to the linker...
224+ template ::rack::widget::Widget *::StoneyDSP::StoneyVCV::createWidgetSized<::rack::widget::Widget>(::rack::math::Vec pos, ::rack::math::Vec size);
225+
226+ // ==============================================================================
206227
207228/* *
208229 * @brief Creates a `Widget` subclass with its top-left at a position.
@@ -219,53 +240,169 @@ inline TWidget *createWidgetCenteredSized(::rack::math::Vec pos, ::rack::math::V
219240 o->box .size = size;
220241 return o;
221242}
243+ // Explicit instantiations to ensure the definition is visible to the linker...
244+ template ::rack::widget::Widget *::StoneyDSP::StoneyVCV::createWidgetCenteredSized<::rack::widget::Widget>(::rack::math::Vec pos, ::rack::math::Vec size);
245+
246+ // ==============================================================================
247+
248+ /* *
249+ * @brief
250+ *
251+ * @tparam
252+ *
253+ * @param pos
254+ * @param module
255+ * @param inputId
256+ *
257+ * @return
258+ */
259+ template <class TParamWidget = ::rack::app::ParamWidget>
260+ inline TParamWidget *createParamWidget (::rack::math::Vec pos, ::rack::engine::Module* module , int paramId)
261+ {
262+ using namespace rack ;
263+
264+ static_assert (::std::is_base_of<::rack::app::ParamWidget, TParamWidget>::value, " TParamWidget must be derived from rack::app::ParamWidget" );
265+
266+ TParamWidget* o = new TParamWidget;
267+ o->box .pos = pos;
268+ o->app ::ParamWidget::module = module ;
269+ o->app ::ParamWidget::paramId = paramId;
270+ o->initParamQuantity ();
271+ return o;
272+ }
273+ // Explicit instantiations to ensure the definition is visible to the linker...
274+ template ::rack::app::ParamWidget *::StoneyDSP::StoneyVCV::createParamWidget<::rack::app::ParamWidget>(::rack::math::Vec pos, ::rack::engine::Module* module , int paramId);
275+
276+ // ==============================================================================
277+
278+ /* *
279+ * @brief
280+ *
281+ * @tparam
282+ *
283+ * @param pos
284+ * @param module
285+ * @param inputId
286+ *
287+ * @return
288+ */
289+ template <class TParamWidget = ::rack::app::ParamWidget>
290+ inline TParamWidget *createParamWidgetCentered (::rack::math::Vec pos, ::rack::engine::Module* module , int paramId)
291+ {
292+ TParamWidget* o = ::StoneyDSP::StoneyVCV::createParamWidget<TParamWidget>(pos, module , paramId);
293+ o->box .pos = o->box .pos .minus (o->box .size .div (2 ));
294+ return o;
295+ }
296+ // Explicit instantiations to ensure the definition is visible to the linker...
297+ template ::rack::app::ParamWidget *::StoneyDSP::StoneyVCV::createParamWidgetCentered<::rack::app::ParamWidget>(::rack::math::Vec pos, ::rack::engine::Module* module , int paramId);
222298
299+ // ==============================================================================
300+
301+ /* *
302+ * @brief
303+ *
304+ * @tparam
305+ *
306+ * @param pos
307+ * @param module
308+ * @param inputId
309+ *
310+ * @return
311+ */
223312template <class TPortWidget = ::rack::app::PortWidget>
224313inline TPortWidget *createInput (::rack::math::Vec pos, ::rack::engine::Module *module , int inputId)
225314{
226315 // Import some namespaces for convenience
227316 using namespace ::rack;
228317
318+ static_assert (::std::is_base_of<::rack::app::PortWidget, TPortWidget>::value, " TPortWidget must be derived from rack::app::PortWidget" );
319+
229320 TPortWidget *o = new TPortWidget;
230321 o->box .pos = pos;
231322 o->app ::PortWidget::module = module ;
232323 o->app ::PortWidget::type = ::rack::engine::Port::INPUT;
233324 o->app ::PortWidget::portId = inputId;
234325 return o;
235326}
327+ // Explicit instantiations to ensure the definition is visible to the linker...
328+ template ::rack::app::PortWidget *::StoneyDSP::StoneyVCV::createInput<::rack::app::PortWidget>(::rack::math::Vec pos, ::rack::engine::Module *module , int inputId);
236329
330+ // ==============================================================================
237331
332+ /* *
333+ * @brief
334+ *
335+ * @tparam
336+ *
337+ * @param pos
338+ * @param module
339+ * @param inputId
340+ *
341+ * @return
342+ */
238343template <class TPortWidget = ::rack::app::PortWidget>
239344inline TPortWidget *createInputCentered (::rack::math::Vec pos, ::rack::engine::Module* module , int inputId)
240345{
241346 TPortWidget *o = ::StoneyDSP::StoneyVCV::createInput<TPortWidget>(pos, module , inputId);
242347 o->box .pos = o->box .pos .minus (o->box .size .div (2 ));
243348 return o;
244349}
350+ // Explicit instantiations to ensure the definition is visible to the linker...
351+ template ::rack::app::PortWidget *::StoneyDSP::StoneyVCV::createInputCentered<::rack::app::PortWidget>(::rack::math::Vec pos, ::rack::engine::Module *module , int inputId);
245352
353+ // ==============================================================================
246354
355+ /* *
356+ * @brief
357+ *
358+ * @tparam
359+ *
360+ * @param pos
361+ * @param module
362+ * @param outputId
363+ *
364+ * @return
365+ */
247366template <class TPortWidget = ::rack::app::PortWidget>
248367inline TPortWidget* createOutput (::rack::math::Vec pos, ::rack::engine::Module *module , int outputId)
249368{
250369 // Import some namespaces for convenience
251370 using namespace ::rack;
252371
372+ static_assert (::std::is_base_of<::rack::app::PortWidget, TPortWidget>::value, " TPortWidget must be derived from rack::app::PortWidget" );
373+
253374 TPortWidget *o = new TPortWidget;
254375 o->box .pos = pos;
255376 o->app ::PortWidget::module = module ;
256377 o->app ::PortWidget::type = ::rack::engine::Port::OUTPUT;
257378 o->app ::PortWidget::portId = outputId;
258379 return o;
259380}
381+ // Explicit instantiations to ensure the definition is visible to the linker...
382+ template ::rack::app::PortWidget *::StoneyDSP::StoneyVCV::createOutput<::rack::app::PortWidget>(::rack::math::Vec pos, ::rack::engine::Module *module , int inputId);
260383
384+ // ==============================================================================
261385
386+ /* *
387+ * @brief
388+ *
389+ * @tparam
390+ *
391+ * @param pos
392+ * @param module
393+ * @param outputId
394+ *
395+ * @return
396+ */
262397template <class TPortWidget = ::rack::app::PortWidget>
263398inline TPortWidget *createOutputCentered (::rack::math::Vec pos, ::rack::engine::Module *module , int outputId)
264399{
265400 TPortWidget *o = ::StoneyDSP::StoneyVCV::createOutput<TPortWidget>(pos, module , outputId);
266401 o->box .pos = o->box .pos .minus (o->box .size .div (2 ));
267402 return o;
268403}
404+ // Explicit instantiations to ensure the definition is visible to the linker...
405+ template ::rack::app::PortWidget *::StoneyDSP::StoneyVCV::createOutputCentered<::rack::app::PortWidget>(::rack::math::Vec pos, ::rack::engine::Module *module , int inputId);
269406
270407// ==============================================================================
271408
@@ -277,6 +414,9 @@ inline TPortWidget *createOutputCentered(::rack::math::Vec pos, ::rack::engine::
277414 // / @} group StoneyDSP
278415} // namespace StoneyDSP
279416
417+ // ==============================================================================
418+
419+
280420// ==============================================================================
281421
282422/* *
0 commit comments