Namespace Woes


I have two modules that are very similar: “Digital Sequencer” and “Digital Sequencer MC”. Some of the class names used by both are the same. For example, both use a VoltageSequencer object defined in “VoltageSequencer.hpp” which is not shared between them.

In other words, I have:

  • src/DigitalSequencer/VoltageSequencer.hpp
  • src/DigitalSequencerXP/VoltageSequencer.hpp

Each .hpp file contains

struct VoltageSequencer : Sequencer
   // stuff

At one point, I found out that both modules were using only 1 version of VoltageSequencer. So I tried to fix it by using namespaces.

#include "plugin.hpp"
#include "osdialog.h"
#include "settings.hpp"

// These two includes are required for Mac
#include <fstream>
#include <array>

#include "DigitalSequencer/defines.h"
#include "Common/Theme.hpp"
#include "Common/components/VoxglitchComponents.hpp"

namespace dseq
  #include "DigitalSequencer/Sequencer.hpp"
  #include "DigitalSequencer/VoltageSequencer.hpp"
  #include "DigitalSequencer/GateSequencer.hpp"
  #include "DigitalSequencer/DigitalSequencer.hpp"
  #include "DigitalSequencer/SequencerDisplay.hpp"
  #include "DigitalSequencer/VoltageSequencerDisplay.hpp"
  #include "DigitalSequencer/GateSequencerDisplay.hpp"
  #include "DigitalSequencer/DigitalSequencerWidget.hpp"

Model* modelDigitalSequencer = createModel<dseq::DigitalSequencer, dseq::DigitalSequencerWidget>("digitalsequencer");

You might be thinking, “Hey Bret, that’s totally the wrong way to do it.” I don’t claim to be good at this stuff, so I’m all ears!

The thing is, this compiled just fine on Windows. However, after submitting these to the library, they produced an error (which I assume is because of the Mac compiler):

src/DigitalSequencer/DigitalSequencer.hpp:132:7: error: cannot initialize object parameter of type ‘rack::engine::Module’ with an expression of type ‘dseq::DigitalSequencer’
getParamQuantity(SEQUENCER_LENGTH_KNOBS + i)->randomizeEnabled = false;

It seems to me that something about my name spacing is throwing off Rack.

My question is: Would anyone have any suggestions for properly namespacing my variables without causing these errors? Or maybe point me to an example of it done well?


Hi @clone45! It would help to see the entire source code with matching line numbers. Is it available on GitHub?

Hi Don! Sure thing! I appreciate the second set of eyes.

Here’s where I tried to differentiate things with a namespace. Here’s Digital Sequencer:

And here’s Digital Sequencer “XP”:

Here’s where the error was thrown: (Although, L131 also threw an error.)

There were a variety of errors, and I selected just one for illustration in my original post. If you want to see all of the errors, check out: Build failure on macOS platform · Issue #169 · clone45/voxglitch · GitHub

Some of those errors unrelated.

I hope that this helps!

OK, that helps a lot! I cloned your GitHub repo on my Linux system and ran the same cross-platform build the VCV Rack maintainers use. I am able to see the same build errors from the Mac compiler. The first one looks like a missing #include <array>:

In file included from src/DigitalSequencer.cpp:25:
src/DigitalSequencer/VoltageSequencer.hpp:3:42: error: implicit instantiation of undefined template 'std::array<float, 32>'
  std::array<float, MAX_SEQUENCER_STEPS> sequence;


I’m guessing there is some disagreement about how the different C++ compilers handle a namespace wrapped around some #includes. So my guess about this error:

In file included from src/DigitalSequencer.cpp:25:
src/DigitalSequencer/VoltageSequencer.hpp:27:21: error: cannot initialize object parameter of type 'dseq::Sequencer' with an expression of type 'dseq::VoltageSequencer'

Comes from the very first line of your file src/DigitalSequencer/VoltageSequencer.hpp:

struct VoltageSequencer : Sequencer

My guess is the Mac compiler is picking an unexpected namespace’s Sequencer to inherit from? Putting the namespace wrapper around #include is an unusual thing to do, and different C++ compilers may not interpret the ISO standard the same way.

What I would suggest trying is this: instead of using namespaces, just give your types unique names. I suggest not having two different types with the same name. Go through your code and rename structs/classes as needed, then remove the namespace wrappers around all the #includes. I think it will be less confusing for you going forward also.

I’m guessing you do not have a Linux system handy for doing the cross-compiling? If possible, using Linux with the “rack-plugin-toolchain” will make sure your submissions go smoothly. But if all you have right now is Windows, I get it.

If it helps, before you submit to VCV Rack again, just push your changes to GitHub and notify me here. I can pull and do a test build for Linux, Windows, and Mac all using a single command, the same way they do, and shoot back any warnings/errors.

By the way, here is a place you probably meant to use "SequencerSelectButton" + std::to_string(i). (There are a few more like this.)

src/DigitalSequencer/DigitalSequencer.hpp:129:94: warning: adding 'unsigned int' to a string does not append to the string [-Wstring-plus-int]
      configParam(SEQUENCER_SELECTION_BUTTONS + i, 0.f, 1.f, 0.f, "SequencerSelectionButton" + i);

Thanks Don!!

This is a huge help to me. I can’t thank you enough for spending the time to look into the issues. The issues unrelated to namespaces I figured out on my own. And it’s ironic, but I had given my types unique names previously to solve the problem, but felt adventurous and tried (and failed) to use namespaces to resolve the conflicts.

I have a lot of menu classes that I’ve broken out into a folder and separate files:

I suppose that I can make them all uniquely named, or move them all back into the Widget.hpp file (such as DigitalSequencerWidget.hpp), which is how they were before and resolves any conflicts.

Anyhow, again, thank you so much for your advice!