JUCE 6: why is a new default plugin project requiring "juce::" in front of everything?

I don’t seem to remember this being the case in JUCE 5…

EDIT: OK, I see there is a setting in the Projucer “add using namespace juce to JuceHeader.h” which defaults to DISABLED in a new audio plugin project.

Why would you want this to be disabled?

Because defining common names (such as Point and AudioBuffer) in the global scope can lead to ambiguities or clashes. See the following threads for the recent pain that not using juce:: by default resulted in:

6 Likes

So are you seriously supposed to put juce:: in front of every single juce class and reference all throughout your code, or is there some other way to handle this?

I remember the time when “using namespace std” was the first line of code you wrote on every c++ program. Then it got banned for good reasons, the same “using namespace juce” has left us now.

Alternative to putting juce:: in front of everything: the using keyword as a type alias for the selected juce classes you plan to use in your module/app.

2 Likes

Thanks. Can you give me an example of the syntax for that, and which file you would put it in?

see also:

https://en.cppreference.com/w/cpp/language/type_alias
https://en.cppreference.com/w/cpp/language/using_declaration

This is how you get the famous “Reference is ambiguous”…

namespace one{
class ImAmbiguous {public : ImAmbiguous(){std::cout << “ONE!” << std::endl;};};
}

namespace two{
class ImAmbiguous {public : ImAmbiguous(){std::cout << “TWO!” << std::endl;};};
}

using namespace one;
using namespace two;

int main (int argc, char* argv[ ])
{
ImAmbiguous whoAmI; // I could prefix the namespace here :slight_smile:
return 0;
}

If you take out all the ‘using namespace declarations’ you can go by either using declaration or type alias

namespace one{
class ImAmbiguous {public : ImAmbiguous(){std::cout << “ONE!” << std::endl;};};
}

namespace two{
class ImAmbiguous {public : ImAmbiguous(){std::cout << “TWO!” << std::endl;};};
}

int main (int argc, char* argv[ ])
{
//using declaration
using one::ImAmbiguous;
ImAmbiguous whoAmI;

//type alias
using NotAmbiguous = two::ImAmbiguous;
NotAmbiguous iKnowWhoYouAre;
return 0;
}

As jules points out here:

you need to encapsulate your “using” declarations as much as possible, not to stomp back on the feet of the other namespaces … I tend to either accept the fact I have to prefix the namespace, or put a using for each object I’ll use encapsulated in the class declaration. this can be also used to make code more readable, highlighting the purpose I’m going to use an object for, like;

class MyClass {
public:
using MyFantasticDataStorageObject = juce::Valuetree;

5 Likes

Thanks for that comprehensive response. Although, when I think of the amount of code editing that likely would be necessary for my current projects to support this, I cringe. If I’m not having a problem, maybe it’s OK to leave it as it is? Or does that mean I will have a problem in the future, like when I move to Xcode 11?

My approach for large bodies of code that are now suffering from this problem is to use DONT_SET_USING_JUCE_NAMESPACE to switch off the clashing namespace, then go through prefixing juce:: as necessary in any headers that now can’t find things in the juce namespace (which admittedly can take a bit of time but is pretty easy work), and then add using namespace juce; to any .cpp files (after all headers are included) to avoid having to go through and prefix everything in those as well.

4 Likes

Hi. I faced the same issue a few months back - tbh, it didn’t take that long to go through all the header files and sort it out - you don’t need it in the .cpp as the compiler will have resolved the reference by then. Typing juce:: is now as natural as typing std::

A few problems, while trying to implement this.

How do you deal with a template function like juce::Rectangle?

This gives an error: ‘juce::Rectangle’ requires template arguments:

using Rectangle = juce::Rectangle;

This doesn’t work:

using Rectangle<int> = juce:Rectangle<int>;

Secondly, what about a namespace within the juce namespace, such as Colours?

If I have things like Colours::yellow in my code, I can’t quite figure out how to do a using for it.

For class templates:

template <typename T>
using Rectangle = juce::Rectangle<T>;

See https://en.cppreference.com/w/cpp/language/type_alias for reference.

For namespaces:

namespace Colours = juce::Colours;

See https://en.cppreference.com/w/cpp/language/namespace_alias for reference.

3 Likes

Thanks so much! I’ve never had to use this syntax before…

One more question: what about juce functions like jmin, jmax etc.?

I don’t think you can specify with the using keyword, it doesn’t work. You can do this:

#define jmin(a,b)   juce::jmin(a,b)

NONONONONONO!!! That’s one of the worst atrocities we’ve seen on the forum for a long time!! :slight_smile:

PLEASE nobody copy this idea!

And seriously folks: just stop grumbling and put juce:: in front of the names!

It’s how you’re supposed to write modern C++. It’s not a big deal to do it, and in the long run you’ll be glad you did it that way.

If you find yourself about to write using namespace [anything], then please stop and think very very carefully before doing it. Only use it as a last resort, and treat it as a bad code smell if you decide you have to do it. Occasionally, you’ll write some code where it makes the code better if you “use a namespace” inside a function, or inside a class - i.e. just within a very small scope. But using namespaces for whole swathes of your codebase is really bad style.

Most of the work I do nowadays is not on the juce codebase itself, but on other (big!) projects which use it, and in all of them, we never import any external namespaces. That means we have many many juce:: and std:: (and other even longer) prefixes scattered around, but this adds information that helps a reader know where things come from.

One other thing I’d mention here is that if you’re going through your old code adding juce:: and it feels that you’re getting sore fingers from having to add it everywhere, then I bet that’s because you’re not using auto enough. When you stick to modern c++ practices with heavy use of auto and type inference, then you end up writing actual type names far less often.

13 Likes

For functions:

using juce::jmin;

See https://en.cppreference.com/w/cpp/language/namespace (syntax 6) for reference.

1 Like

Yeah, I agree - sorry for posting it :slight_smile: - that’s why I was looking for a better way.

I was sort of trying, as an experiment, to see if I could accomplish this removal of the juce namespace with just some header file inclusions. I wasn’t familiar with the syntax for the using keyword with functions…

Thanks, that’s a good reference page.

Sure, but it’ll be better if your experiment fails, and instead you just do things properly and add the prefix everywhere :slight_smile:

It’s all really my fault for leaving using namespace juce turned on by default for so long (and doing example code that works that way). Would have been better if that had never existed!

4 Likes

Is there a good reason to use the form:

using SomeType = juce::SomeType;

over this one?

using juce::SomeType;

I looked at that namespace reference page, and I don’t quite understand the difference.

They both seem to work the same, at least in my code, and the second one is easier. Furthermore, the second form works for templated types without specifying a template.

The first makes the symbol SomeType a synonym for juce::SomeType, aka an alias.

The second makes the name SomeType, from namespace juce. accessible for unqualified lookup.

Since the second form expresses the intent more clearly, I would use that one. I use the first form to replace anywhere I would use a typedef.

1 Like