1
0
mirror of https://github.com/cookiengineer/audacity synced 2025-06-16 16:10:06 +02:00

Define make_unique properly, use in at least one commonly visited place...

Which is file opening.

So we can be sure it compiles and works on all platforms.
This commit is contained in:
Paul Licameli 2016-02-14 21:30:39 -05:00
parent 7f223c261a
commit 7988e814bd
2 changed files with 54 additions and 16 deletions

View File

@ -171,23 +171,62 @@ void QuitAudacity();
#define safenew new
#if !defined(__WXMSW__)
/* replicate the very useful C++14 make_unique for those build environments
that don't implement it yet.
typical useage:
auto p = std::make_unique<Myclass>(ctorArg1, ctorArg2, ... ctorArgN);
p->DoSomething();
auto q = std::make_unique<Myclass[]>(count);
q[0].DoSomethingElse();
The first hides naked new and delete from the source code.
The second hides new[] and delete[]. Both of course ensure destruction if
you don't use something like std::move(p) or q.release(). Both expressions require
that you identify the type only once, which is brief and less error prone.
(Whereas this omission of [] might invite a runtime error:
std::unique_ptr<Myclass> q { new Myclass[count] }; )
Some C++11 tricks needed here are (1) variadic argument lists and
(2) making the compile-time dispatch work correctly. You can't have
a partially specialized template function, but you get the effect of that
by other metaprogramming means.
*/
namespace std {
// replicate make_unique, enough for our purposes
// For overloading resolution
template <typename X> struct __make_unique_result {
using scalar_case = unique_ptr<X>;
};
// "scalar" version
template<class X, class... Args> inline
unique_ptr<X> make_unique(Args&&... args)
{
return (unique_ptr<X>(safenew X(forward<Args>(args)...)));
}
// Partial specialization of the struct for array case
template <typename X> struct __make_unique_result<X[]> {
using array_case = unique_ptr<X[]>;
using element = X;
};
// array version
template<class X> inline
unique_ptr<X[]> make_unique(size_t count)
{
return (unique_ptr<X[]>(safenew X[count]()));
}
// Now the scalar version of unique_ptr
template<typename X, typename... Args> inline
typename __make_unique_result<X>::scalar_case
make_unique(Args&&... args)
{
return typename __make_unique_result<X>::scalar_case
{ safenew X( forward<Args>(args)... ) };
}
// Now the array version of unique_ptr
// The compile-time dispatch trick is that the non-existence
// of the scalar_case type makes the above overload
// unavailable when the template parameter is explicit
template<typename X> inline
typename __make_unique_result<X>::array_case
make_unique(size_t count)
{
return typename __make_unique_result<X>::array_case
{ safenew typename __make_unique_result<X>::element[count] };
}
}
#endif

View File

@ -217,15 +217,14 @@ bool XMLTagHandler::ReadXMLTag(const char *tag, const char **attrs)
// const char **out_attrs = NEW char (const char *)[tmp_attrs.GetCount()+1];
// however MSVC doesn't like the constness in this position, so this is now
// added by a cast after creating the array of pointers-to-non-const chars.
const wxChar **out_attrs = (const wxChar**)new wxChar *[tmp_attrs.GetCount()+1];
auto out_attrs = std::make_unique<const wxChar *[]>(tmp_attrs.GetCount() + 1);
for (size_t i=0; i<tmp_attrs.GetCount(); i++) {
out_attrs[i] = tmp_attrs[i].c_str();
}
out_attrs[tmp_attrs.GetCount()] = 0;
bool result = HandleXMLTag(UTF8CTOWX(tag).c_str(), out_attrs);
bool result = HandleXMLTag(UTF8CTOWX(tag).c_str(), out_attrs.get());
delete[] out_attrs;
return result;
}