OwnedHashMap?


#1

Hi,

I use OwnedArray a lot, it's a very helpful container. Although there are situations where I rather have a key instead of an index in array, which might change.

The HashMap seems to be the thing to use, but for Objects like Component the HashMap is not usable, because HashMap requires the values to be copyable, but e.g. a Component is deliberatly not copyable.

Using pointers in the HashMap is even more dangerous, because when a second pointer is added in the hashmap, the object will never get deleted.

A container like a OwnedHashMap would be great. Any chance to get something alike? Or is there already an easy way to achieve this?

Thanks,

Daniel


#2

This might use useful, this is the C++11/14 way (though probably use unordered_map rather than map): 

http://stackoverflow.com/questions/16923748/c-inserting-unique-ptr-in-map

It might be possible with the JUCE containers but I've not tried it - I suspect there'd be a copyability problem with doing a HashMap containing the ScopedPointer.


#3

Yes, that seemed like the way to go. Unfortunately the ScopedPointer is not copyable either:

juce_ScopedPointer.h: 223

JUCE_DECLARE_NON_COPYABLE (ScopedPointer)

The problem seems not to be that the types are not copyable, but rather the strong desire of the HashMap to copy anything you confide to it.

Thanks anyway, any other idea?


#4

I would go for a std::unordered_map<Key, std::unique_ptr<T>>. This works very nicely.


#5

Thanks Timur, I tried that, but unordered_map is a C++11 feature, which still does not work correctly here. I can't reproduce it, but setting the C++11 flag in introjucer in a new project transforms into build settings, but sometimes not.

And even worse, when I work for some time with the jucer files (adding and removing classes), at some point the C++11 setting vanishes and gets compiler default again.

And even changing Compiler-Language to C++11 or C++14 in XCode, call clean and build does not help. The unordered_map is still not recognized.

That's why I don't use C++11 until it becomes default, I spent too much time in that fragile workflow... (also bad for the AudioProcessorValueTreeState, would really liked to test it)...


#6

C++11 has been the default in Xcode for some time! I think since Xcode 5. You should definitely use it! I can't see any reason at all to keep using C++98 on Xcode these days (unless you absolutely depend on legacy code you can't recompile with C++11, which is a very unfortunate situation...)

If there is a bug in Introjucer that prevents you from using C++11 properly, please post a reproduction scenario and I'll fix it rightaway.

If you are using C++11 with Xcode and use non-default build settings, please make sure you have set "libc++" as your C++ standard library (which is also the default...). Also, remember to #include <unordered_map>.

I just tried it creating a new project in the Introjucer with the default settings: C++11 and std::unordered_map work like a charm.


#7

Quite a lot of audio people still use Snow Leopard, which has no C++11 standard library support. Though thankfully the number is diminishing now it seems.


#8

I think you are overestimating the number of people who are still on Snow Leopard. According to our info, there is actually very few of them left.

May I ask why you are stuck on such an ancient system? No matter how hard I think I can't come up with a good reason. Would be really curious to know what the motivation for not upgrading is? Maybe I'm missing something here...

Also, unfortunately we can't support such old versions of OSX and Xcode here in the JUCE team, so really sorry but we won't accept feature requests or bug reports related to that.


#9

Last year in Tracktion we moved to C++11 and dropped support for 10.6. We only had one user complain.


#10

Yes, this is consistent with what I heard from other people as well. Thanks Dave for the info!

At the JUCE summit, at some point during my workshop I asked a room full of JUCE devs whether anyone was still on C++98 and as far as I remember no hands went up.


#11

C++11 has been the default in Xcode for some time! I think since Xcode 5. You should definitely use it!

It's not that I don't want to, I really do! But it does not work...

Also, remember to #include <unordered_map>

dough! I didn't... But nevertheless, it says file not found. I checked it using find / grep in /Applications/XCode:

./Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS.sdk/usr/include/c++/4.2.1/tr1/unordered_map
./Contents/Developer/Platforms/AppleTVSimulator.platform/Developer/SDKs/AppleTVSimulator.sdk/usr/include/c++/4.2.1/tr1/unordered_map
./Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/c++/4.2.1/tr1/unordered_map
./Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include/c++/4.2.1/tr1/unordered_map
./Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/c++/4.2.1/tr1/unordered_map
./Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/unordered_map


But the compiler says:

CompileC /Users/daniel/Library/Developer/Xcode/DerivedData/AK-MonitorMatrix-hhwilcxkmjeajpasleuchvnubtjm/Build/Intermediates/AK-MonitorMatrix.build/Debug/AK-MonitorMatrix.build/Objects-normal/x86_64/PluginProcessor.o /Volumes/data/Developer/AK-MonitorMatrix/Source/PluginProcessor.cpp normal x86_64 c++ com.apple.compilers.llvm.clang.1_0.compiler
    cd /Volumes/data/Developer/AK-MonitorMatrix/Builds/MacOSX
    export LANG=en_US.US-ASCII
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -x c++ -arch x86_64 -fmessage-length=0 -fdiagnostics-show-note-include-stack -fmacro-backtrace-limit=0 -std=c++11 -Wno-trigraphs -fpascal-strings -O0 -Wno-missing-field-initializers -Wno-missing-prototypes -Wnon-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -Wno-missing-braces -Wparentheses -Wswitch -Wno-unused-function -Wno-unused-label -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-empty-body -Wno-uninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-conversion -Wno-constant-conversion -Wno-int-conversion -Wno-bool-conversion -Wno-enum-conversion -Wno-shorten-64-to-32 -Wno-newline-eof -Wno-c++11-extensions -D_DEBUG=1 -DDEBUG=1 -DJUCER_XCODE_MAC_F6D2F4CF=1 -DJUCE_APP_VERSION=1.0.0 -DJUCE_APP_VERSION_HEX=0x10000 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk -fasm-blocks -fstrict-aliasing -Wdeprecated-declarations -Winvalid-offsetof -mmacosx-version-min=10.8 -g -fvisibility-inlines-hidden -Wno-sign-conversion -iquote /Users/daniel/Library/Developer/Xcode/DerivedData/AK-MonitorMatrix-hhwilcxkmjeajpasleuchvnubtjm/Build/Intermediates/AK-MonitorMatrix.build/Debug/AK-MonitorMatrix.build/AK-MonitorMatrix-generated-files.hmap -I/Users/daniel/Library/Developer/Xcode/DerivedData/AK-MonitorMatrix-hhwilcxkmjeajpasleuchvnubtjm/Build/Intermediates/AK-MonitorMatrix.build/Debug/AK-MonitorMatrix.build/AK-MonitorMatrix-own-target-headers.hmap -I/Users/daniel/Library/Developer/Xcode/DerivedData/AK-MonitorMatrix-hhwilcxkmjeajpasleuchvnubtjm/Build/Intermediates/AK-MonitorMatrix.build/Debug/AK-MonitorMatrix.build/AK-MonitorMatrix-all-target-headers.hmap -iquote /Users/daniel/Library/Developer/Xcode/DerivedData/AK-MonitorMatrix-hhwilcxkmjeajpasleuchvnubtjm/Build/Intermediates/AK-MonitorMatrix.build/Debug/AK-MonitorMatrix.build/AK-MonitorMatrix-project-headers.hmap -I/Volumes/data/Developer/AK-MonitorMatrix/Builds/MacOSX/build/Debug/include -I/Volumes/data/Developer/SDK/VST3\ SDK -I../../JuceLibraryCode -I../../../JUCE-OSX/modules -I/Volumes/data/Developer/SDK/AAX_SDK -I/Volumes/data/Developer/SDK/AAX_SDK/Interfaces -I/Volumes/data/Developer/SDK/AAX_SDK/Interfaces/ACF -I/Users/daniel/Library/Developer/Xcode/DerivedData/AK-MonitorMatrix-hhwilcxkmjeajpasleuchvnubtjm/Build/Intermediates/AK-MonitorMatrix.build/Debug/AK-MonitorMatrix.build/DerivedSources/x86_64 -I/Users/daniel/Library/Developer/Xcode/DerivedData/AK-MonitorMatrix-hhwilcxkmjeajpasleuchvnubtjm/Build/Intermediates/AK-MonitorMatrix.build/Debug/AK-MonitorMatrix.build/DerivedSources -Wreorder -F/Volumes/data/Developer/AK-MonitorMatrix/Builds/MacOSX/build/Debug -MMD -MT dependencies -MF /Users/daniel/Library/Developer/Xcode/DerivedData/AK-MonitorMatrix-hhwilcxkmjeajpasleuchvnubtjm/Build/Intermediates/AK-MonitorMatrix.build/Debug/AK-MonitorMatrix.build/Objects-normal/x86_64/PluginProcessor.d --serialize-diagnostics /Users/daniel/Library/Developer/Xcode/DerivedData/AK-MonitorMatrix-hhwilcxkmjeajpasleuchvnubtjm/Build/Intermediates/AK-MonitorMatrix.build/Debug/AK-MonitorMatrix.build/Objects-normal/x86_64/PluginProcessor.dia -c /Volumes/data/Developer/AK-MonitorMatrix/Source/PluginProcessor.cpp -o /Users/daniel/Library/Developer/Xcode/DerivedData/AK-MonitorMatrix-hhwilcxkmjeajpasleuchvnubtjm/Build/Intermediates/AK-MonitorMatrix.build/Debug/AK-MonitorMatrix.build/Objects-normal/x86_64/PluginProcessor.o

/Volumes/data/Developer/AK-MonitorMatrix/Source/PluginProcessor.cpp:14:10: fatal error: 'unordered_map' file not found
#include <unordered_map>
         ^
1 error generated.

The root path of the includes is unfortunately not visible in the compiler call, so I don't know, if it's my fault or his...

Regarding the AudioProcessorValueTreeState, I get "unknown type". So I checked the source "juce_AudioProcessorValueTreeState.h" and see the preprocessor checking for JUCE_COMPILER_SUPPORTS_LAMBDAS and it seems to be unset. Then I override it via introjucer - extra preprocessor definitions "JUCE_COMPILER_SUPPORTS_LAMBDAS=1" and then I get 

In file included from /Volumes/data/Developer/AK-MonitorMatrix/Source/PluginEditor.cpp:11:
In file included from /Volumes/data/Developer/AK-MonitorMatrix/Source/PluginProcessor.h:14:
In file included from /Volumes/data/Developer/AK-MonitorMatrix/Source/../JuceLibraryCode/JuceHeader.h:18:
In file included from ../../JuceLibraryCode/modules/juce_audio_devices/juce_audio_devices.h:4:
In file included from ../../JuceLibraryCode/modules/juce_audio_devices/../../../../JUCE-OSX/modules/juce_audio_devices/juce_audio_devices.h:28:
In file included from ../../JuceLibraryCode/modules/juce_audio_devices/../../../../JUCE-OSX/modules/juce_audio_devices/../juce_events/juce_events.h:34:
../../JuceLibraryCode/modules/juce_audio_devices/../../../../JUCE-OSX/modules/juce_audio_devices/../juce_events/messages/juce_MessageManager.h:97:33: error: no type named 'function' in namespace 'std'
    static void callAsync (std::function<void(void)>);
                           ~~~~~^

...not a big surprise, the compiler told me that he has no lambdas, if I start messing with defines...

And that's all happening in a fresh project with in introjucer and checken XCode, C++11 is set correctly (N.B. OSW 10.10, XCode 7.2)...

I just tried it creating a new project in the Introjucer with the default settings: C++11 and std::unordered_map work like a charm.

I envy you ;-)

It's "killing me slowly"...


#12

I did not do a decision, I always went with the default, if C++11 was default, then I always was on C++11, sorry for the confusion. I never spent a thought, until I was told "if your AudioProcessorValueTreeState does not work, you have to switch to C++11".

I usually design on a higher level and relied on the tools and ide's to take care of the rest (which was Qt-Creator/Qmake before since 2000 and now after a five years break JUCE for 5 months...)


#13

Well if the compiler told you it doesn't have lambdas, then clearly you are compiling in C++98 and not in C++11. Something is very wrong in your setup. You should never mess with those preprocessor macros yourself.

Also, looking at your compiler flags, if you have -std=c++11 then you also need -stdlib=libc++ otherwise none of it will work.


#14

Are you sure you are using a current version of Xcode?

Here's a test: open up Xcode. Create a new C++ command line application from scratch (not using Introjucer or JUCE, just plain Xcode C++). 

New -> Project -> OSX -> Application -> Command LIne Tool -> Next -> Language: C++

Then you get a main function with just a "Hello World" in it, using the default compiler settings. On Xcode 7, those are C++11 and libc++. 

Don't touch any build settings. In that main.cpp, just do an #include <unordered_map> and instantiate a std::unordered_map inside the main function.

Does that compile? Because if it doesn't, then your Xcode is somehow badly screwed up...


#15

You should never mess with those preprocessor macros yourself.

I know, that's what I tried to say in my sarcastic comment, but I wanted to make sure that I have tried everything...

With the knowledge, that the default should do what I need, I started over and leave every setting, including C++ language on "Compiler default", and it works, the unordered_map is found. However, I am not on 10.11 and therefore my code will not run. I set deployment target, and because I expect people, I want to sell my plugin to (if I ever reach that day) may have something older, I used to choose 10.8. And then I don't have the unordered_map...

Also if I deploy to 10.10 with default settings, I can finally use the AudioProcessorValueTreeState, yay :-)

So conclusive I can say I can use C++11 features as long as I deploy to 10.10, for the moment that's fine, but when I'm shipping, is it really impossible to serve 10.8 customers as well? That's not so long ago, is it?

Sorry if I sound sometimes a little negative, I hate poking in the mud. I really appreaciate your help, so if I didn't say it often enough, once again: thanks a lot!


#16

Hang on. You don't actually need to compile on OSX 10.8 in order to serve 10.8 customers. You can happily compile on OSX 10.11 using Xcode 7 and C++11 and the OSX 10.11 SDK and all the newest stuff.

The only thing you need to do to make sure that your app will still run on 10.8 is to set the "OSX Deployment Target" to 10.8.

Sounds like this is exactly what you are doing? The Deployment Target setting should never mess up anything else. Are you saying that C++11 compilation breaks for you if you just change the deployment target from 10.10 to 10.8? Because that would be super weird...


#17

Are you saying that C++11 compilation breaks for you if you just change the deployment target from 10.10 to 10.8? Because that would be super weird...

That's exactly what I observed. I never tried compiling with deployment target else than 10.8 until today, that's why I always thought, the new features don't work at all for me. The Base SDK I never touched, because I was aware, that this has nothing to do with the system I am deploying to.


#18

OK. Now we're getting somewhere. I can reproduce your problem now. Apparently, the "compiler default" does depend on the Deployment Target. If you set it to 10.8, then the default is not C++11 anymore, and you'd have to set C++11 and libc++ manually (after which everything compiles happily).

However I can also confirm that in this case something is screwed up in the Introjucer and the C++11 setting does not always get carried over correctly to the Xcode project.

I will fix this asap.


#19

...yes, this works as expected.

Now I made a test, empty "Audio Plugin" from introjucer (last pulled Jan. 9th 2016), and here I observed, everything default, added paths for VST3 and AAX and with deployment setting 10.8 - no AudioProcessorValueTreeState and no unordered_map include. And I had to disable AAX, I think because AAX_Library is compiled differently.

Set in introjucer to deployment 10.10 - Save project and open in IDE: voila, AudioProcessorValueTreeState and unordered_map are present and usable.

Now going back to AAX_Library, I don't get it to work again. Opened AAX project, set all settings according to the introjucers projects:

C dialect: Compiler default

C++ dialect: Compiler default

STD lib: Compiler default

Deployment target: tried both 10.8 AND 10.10, the project linking gets not linked to the AAXLibrary due to the std::c_str etc. stuff. Rebuilding AAXLibrary_libcpp didn't help either.

But to make my misfortune perfect: my old project (created in Dec. 13th, 2015) compiles with either version, deployment target 10.8 and 10.10, in any combination of library and project. But there I have no AudioProcessorValueTreeState and no unordered_map. The new project links to no version of the AAXLibrary. I have only one path, there is no second version of the library lying around.

It's probably hard to believe, that I didn't mess with any other setting, but I really didn't... I think I download the AAX-Library new and start from scratch...


#20

Oh wow, you just cut me off the rope, I was about to loose my mind... I didn't see the pattern in it...

And now with this settings in the AAXLibrary, I can also link everything together.

Thanks so much, I almost didn't believe there will be a solution...