refs #624 Use auto function return type deduction.

This commit is contained in:
Mathew Sutcliffe
2016-03-19 23:37:51 +00:00
parent 4700cb1602
commit eb4df2d893
8 changed files with 42 additions and 85 deletions

View File

@@ -93,7 +93,7 @@ namespace BlackMisc
CONTAINER r; CONTAINER r;
if (suffix.isEmpty()) { return r; } if (suffix.isEmpty()) { return r; }
QString sfxUpper(suffix.trimmed().toUpper()); QString sfxUpper(suffix.trimmed().toUpper());
r = this->container().findBy([ = ](const OBJ & csObj) -> bool r = this->container().findBy([ = ](const OBJ & csObj)
{ {
return (csObj.getCallsign().getSuffix() == sfxUpper); return (csObj.getCallsign().getSuffix() == sfxUpper);
}); });

View File

@@ -53,16 +53,16 @@ namespace BlackMisc
//! @} //! @}
//! Return the value at this iterator position. //! Return the value at this iterator position.
auto value() const -> decltype(std::declval<I>().value()) { return m_iterator.value(); } auto value() const { return m_iterator.value(); }
//! Return the key at this iterator position. //! Return the key at this iterator position.
//! @{ //! @{
auto key() const -> decltype(std::declval<I>().key()) { return m_iterator.key(); } auto key() const { return m_iterator.key(); }
auto operator *() const -> decltype(std::declval<I>().key()) { return key(); } auto operator *() const { return key(); }
//! @} //! @}
//! Indirection operator: pointer to the key at this iterator position. //! Indirection operator: pointer to the key at this iterator position.
auto operator ->() const -> typename std::remove_reference<decltype(std::declval<I>().key())>::type * { return &key(); } auto operator ->() const { return &key(); }
//! Equality operators. //! Equality operators.
//! @{ //! @{

View File

@@ -275,7 +275,7 @@ namespace BlackMisc
//! Pass the current value to the functor inspector, and return whatever inspector returns. //! Pass the current value to the functor inspector, and return whatever inspector returns.
template <typename F> template <typename F>
auto read(F &&inspector) -> decltype(inspector(std::declval<const T &>())) auto read(F &&inspector)
{ {
return std::forward<F>(inspector)(read().get()); return std::forward<F>(inspector)(read().get());
} }
@@ -314,14 +314,14 @@ namespace BlackMisc
//! \param function The LockFree values from which this LockFreeMulti was constructed will be passed as arguments to this functor. //! \param function The LockFree values from which this LockFreeMulti was constructed will be passed as arguments to this functor.
//! \return The value returned by the functor, if any. //! \return The value returned by the functor, if any.
template <typename F> template <typename F>
auto operator ()(F &&function) && -> decltype(function(std::declval<Ts>()...)) auto operator ()(F &&function) &&
{ {
return call(std::forward<F>(function), Private::make_index_sequence<sizeof...(Ts)>()); return call(std::forward<F>(function), Private::make_index_sequence<sizeof...(Ts)>());
} }
private: private:
template <typename F, size_t... Is> template <typename F, size_t... Is>
auto call(F &&function, Private::index_sequence<Is...>) -> decltype(function(std::declval<Ts>()...)) auto call(F &&function, Private::index_sequence<Is...>)
{ {
return std::forward<F>(function)(std::get<Is>(m_tup).get()...); return std::forward<F>(function)(std::get<Is>(m_tup).get()...);
} }

View File

@@ -71,31 +71,6 @@ namespace BlackMisc
template <class T> bool operator()(const T &a, const T &b) const { return head.isStable(a, b) ? head(a, b) : tail(a, b); } template <class T> bool operator()(const T &a, const T &b) const { return head.isStable(a, b) ? head(a, b) : tail(a, b); }
}; };
//! \private
template <class T, class M> struct MemberTransform
{
M m;
MemberTransform(M m_) : m(m_) {}
auto operator()(const T &v) const -> decltype((v.*std::declval<M>())()) { return (v.*m)(); }
};
//! \private
template <class T, class M> struct MemberValid
{
M m;
MemberValid(M m_) : m(m_) {}
bool operator()(const T &v) const { return (v.*m)().isValid(); }
};
//! \private
template <class T, class M, class C> struct MemberIsAnyOf
{
M m;
const C &c;
MemberIsAnyOf(M m_, const C &c_) : m(m_), c(c_) {}
bool operator()(const T &v) const { return c.contains((v.*m)()); }
};
//! \private //! \private
template <class T> struct Equals template <class T> struct Equals
{ {
@@ -137,58 +112,44 @@ namespace BlackMisc
} }
/*! /*!
* Transformation function object which returns the value returned by one of it's argument member functions. * Returns a function object that returns the value returned by one of it's argument member functions.
*
* A lambda would usually be easier, but it is difficult to directly return a lambda from a function
* without C++14 deduced return types.
*/ */
template <class T, class R> template <class T, class R>
auto MemberTransform(R(T::*memberFunc)() const) -> Private::MemberTransform<T, decltype(memberFunc)> auto MemberTransform(R(T::*memberFunc)() const)
{ {
return { memberFunc }; return [memberFunc](const T &object) { return (object.*memberFunc)(); };
} }
/*! /*!
* Predicate which is true if the isValid() method of the value returned from one of its member functions returns true. * Returns a predicate that returns true if the isValid() method of the value returned from one of its member functions returns true.
*
* A lambda would usually be easier, but it is difficult to directly return a lambda from a function
* without C++14 deduced return types.
*/ */
template <class T, class R> template <class T, class R>
auto MemberValid(R(T::*memberFunc)() const) -> Private::MemberValid<T, decltype(memberFunc)> auto MemberValid(R(T::*memberFunc)() const)
{ {
return { memberFunc }; return [memberFunc](const T &object) { return (object.*memberFunc)().isValid(); };
} }
/*! /*!
* Predicate which is true if the value returned by its argument's member function can be found in a captured container. * Returns a predicate that returns true if the value returned by its argument's member function can be found in a captured container.
*
* A lambda would usually be easier, but it is difficult to directly return a lambda from a function
* without C++14 deduced return types.
*
* \warning The container is captured by reference, so be careful that it remains valid for the lifetime of the predicate. * \warning The container is captured by reference, so be careful that it remains valid for the lifetime of the predicate.
*/ */
template <class T, class R, class C> template <class T, class R, class C>
auto MemberIsAnyOf(R(T::*memberFunc)() const, const C &container) -> Private::MemberIsAnyOf<T, decltype(memberFunc), C> auto MemberIsAnyOf(R(T::*memberFunc)() const, const C &container)
{ {
return { memberFunc, container }; return [memberFunc, &container](const T &object) { return container.contains((object.*memberFunc)()); };
} }
/*! /*!
* Predicate which is true if its argument compares equal with another, captured value. * Returns a predicate that returns true if its argument compares equal with another, captured value.
*
* A lambda would usually be easier, but it is difficult to directly return a lambda from a function
* without C++14 deduced return types. It is also a generic function object, which is only possible
* with C++14 generic lambdas.
*/ */
template <class T> template <class T>
auto Equals(T &&value) -> Private::Equals<typename std::decay<T>::type> auto Equals(T &&value)
{ {
return { std::forward<T>(value), 0 }; return [value = std::forward<T>(value)](const T &object) { return object == value; };
} }
/*! /*!
* Predicate which is true if its argument matches a captured CPropertyIndexVariantMap. * Returns a predicate that returns true if its argument matches a captured CPropertyIndexVariantMap.
*/ */
inline auto Matches(const CPropertyIndexVariantMap &map) -> Private::Matches inline auto Matches(const CPropertyIndexVariantMap &map) -> Private::Matches
{ {

View File

@@ -27,7 +27,7 @@ namespace BlackMisc
{ {
if (title.isEmpty()) { return false; } if (title.isEmpty()) { return false; }
return this->containsBy( return this->containsBy(
[ = ](const CAircraftCfgEntries & entries) -> bool { return title.compare(entries.getTitle(), caseSensitivity) == 0; } [ = ](const CAircraftCfgEntries & entries) { return title.compare(entries.getTitle(), caseSensitivity) == 0; }
); );
} }
@@ -82,7 +82,7 @@ namespace BlackMisc
CAircraftCfgEntriesList CAircraftCfgEntriesList::findByTitle(const QString &title, Qt::CaseSensitivity caseSensitivity) const CAircraftCfgEntriesList CAircraftCfgEntriesList::findByTitle(const QString &title, Qt::CaseSensitivity caseSensitivity) const
{ {
return this->findBy([ = ](const CAircraftCfgEntries & entries) -> bool return this->findBy([ = ](const CAircraftCfgEntries & entries)
{ return title.compare(entries.getTitle(), caseSensitivity) == 0; }); { return title.compare(entries.getTitle(), caseSensitivity) == 0; });
} }

View File

@@ -75,21 +75,21 @@ namespace BlackMisc
friend class BlackMisc::Private::EncapsulationBreaker; \ friend class BlackMisc::Private::EncapsulationBreaker; \
static_assert(Private::HasEnabledTupleConversion<T>::value, \ static_assert(Private::HasEnabledTupleConversion<T>::value, \
"Missing BLACK_ENABLE_TUPLE_CONVERSION macro in " #T); \ "Missing BLACK_ENABLE_TUPLE_CONVERSION macro in " #T); \
static auto toTuple(const T &o) -> decltype(BlackMisc::tie MEMBERS) \ static auto toTuple(const T &o) \
{ \ { \
return BlackMisc::tie MEMBERS; \ return BlackMisc::tie MEMBERS; \
} \ } \
static auto toTuple(T &o) -> decltype(BlackMisc::tie MEMBERS) \ static auto toTuple(T &o) \
{ \ { \
return BlackMisc::tie MEMBERS; \ return BlackMisc::tie MEMBERS; \
} \ } \
static auto toMetaTuple(const T &o) -> decltype(BlackMisc::tieMeta MEMBERS) \ static auto toMetaTuple(const T &o) \
{ \ { \
auto tu = BlackMisc::tieMeta MEMBERS; \ auto tu = BlackMisc::tieMeta MEMBERS; \
parser().extendMetaTuple(tu); \ parser().extendMetaTuple(tu); \
return tu; \ return tu; \
} \ } \
static auto toMetaTuple(T &o) -> decltype(BlackMisc::tieMeta MEMBERS) \ static auto toMetaTuple(T &o) \
{ \ { \
auto tu = BlackMisc::tieMeta MEMBERS; \ auto tu = BlackMisc::tieMeta MEMBERS; \
parser().extendMetaTuple(tu); \ parser().extendMetaTuple(tu); \
@@ -105,7 +105,7 @@ namespace BlackMisc
return parser().m_names; \ return parser().m_names; \
} \ } \
public: \ public: \
static auto constToTuple(const T &o) -> decltype(BlackMisc::tie MEMBERS) \ static auto constToTuple(const T &o) \
{ \ { \
return BlackMisc::tie MEMBERS; \ return BlackMisc::tie MEMBERS; \
} \ } \
@@ -127,21 +127,21 @@ namespace BlackMisc
friend class BlackMisc::Private::EncapsulationBreaker; \ friend class BlackMisc::Private::EncapsulationBreaker; \
static_assert(Private::HasEnabledTupleConversion<T<U...>>::value, \ static_assert(Private::HasEnabledTupleConversion<T<U...>>::value, \
"Missing BLACK_ENABLE_TUPLE_CONVERSION macro in " #T); \ "Missing BLACK_ENABLE_TUPLE_CONVERSION macro in " #T); \
static auto toTuple(const T<U...> &o) -> decltype(BlackMisc::tie MEMBERS) \ static auto toTuple(const T<U...> &o) \
{ \ { \
return BlackMisc::tie MEMBERS; \ return BlackMisc::tie MEMBERS; \
} \ } \
static auto toTuple(T<U...> &o) -> decltype(BlackMisc::tie MEMBERS) \ static auto toTuple(T<U...> &o) \
{ \ { \
return BlackMisc::tie MEMBERS; \ return BlackMisc::tie MEMBERS; \
} \ } \
static auto toMetaTuple(const T<U...> &o) -> decltype(BlackMisc::tieMeta MEMBERS) \ static auto toMetaTuple(const T<U...> &o) \
{ \ { \
auto tu = BlackMisc::tieMeta MEMBERS; \ auto tu = BlackMisc::tieMeta MEMBERS; \
parser().extendMetaTuple(tu); \ parser().extendMetaTuple(tu); \
return tu; \ return tu; \
} \ } \
static auto toMetaTuple(T<U...> &o) -> decltype(BlackMisc::tieMeta MEMBERS) \ static auto toMetaTuple(T<U...> &o) \
{ \ { \
auto tu = BlackMisc::tieMeta MEMBERS; \ auto tu = BlackMisc::tieMeta MEMBERS; \
parser().extendMetaTuple(tu); \ parser().extendMetaTuple(tu); \
@@ -157,7 +157,7 @@ namespace BlackMisc
return parser().m_names; \ return parser().m_names; \
} \ } \
public: \ public: \
static auto constToTuple(const T<U...> &o) -> decltype(BlackMisc::tie MEMBERS) \ static auto constToTuple(const T<U...> &o) \
{ \ { \
return BlackMisc::tie MEMBERS; \ return BlackMisc::tie MEMBERS; \
} \ } \
@@ -286,7 +286,7 @@ namespace BlackMisc
* \ingroup Tuples * \ingroup Tuples
*/ */
template <class... Ts> template <class... Ts>
auto tie(Ts &&... args) -> decltype(std::make_tuple(Private::tieHelper(args)...)) auto tie(Ts &&... args)
{ {
return std::make_tuple(Private::tieHelper(args)...); return std::make_tuple(Private::tieHelper(args)...);
} }
@@ -296,7 +296,7 @@ namespace BlackMisc
* \ingroup Tuples * \ingroup Tuples
*/ */
template <class... Ts> template <class... Ts>
auto tieMeta(Ts &&... args) -> decltype(std::make_tuple(Private::tieMetaHelper(args)...)) auto tieMeta(Ts &&... args)
{ {
return std::make_tuple(Private::tieMetaHelper(args)...); return std::make_tuple(Private::tieMetaHelper(args)...);
} }

View File

@@ -40,7 +40,7 @@ namespace BlackMisc
{ {
protected: protected:
template <class T> template <class T>
static auto toMetaTuple(T &o) -> decltype(TupleConverter<typename std::decay<T>::type>::toMetaTuple(o)) static auto toMetaTuple(T &o)
{ {
return TupleConverter<typename std::decay<T>::type>::toMetaTuple(o); return TupleConverter<typename std::decay<T>::type>::toMetaTuple(o);
} }
@@ -213,14 +213,14 @@ namespace BlackMisc
// Convert a meta tuple to a value tuple // Convert a meta tuple to a value tuple
template <class Tu, size_t... Is> template <class Tu, size_t... Is>
auto stripMeta(Tu &&tu, index_sequence<Is...>) -> decltype(std::make_tuple(tieHelper(std::get<Is>(std::forward<Tu>(tu)))...)) auto stripMeta(Tu &&tu, index_sequence<Is...>)
{ {
return std::make_tuple(tieHelper(std::get<Is>(std::forward<Tu>(tu)))...); return std::make_tuple(tieHelper(std::get<Is>(std::forward<Tu>(tu)))...);
} }
// Convert a value tuple to a meta tuple with default metadata // Convert a value tuple to a meta tuple with default metadata
template <class Tu, size_t... Is> template <class Tu, size_t... Is>
auto recoverMeta(Tu &&tu, index_sequence<Is...>) -> decltype(std::make_tuple(tieMetaHelper(std::get<Is>(std::forward<Tu>(tu)))...)) auto recoverMeta(Tu &&tu, index_sequence<Is...>)
{ {
return std::make_tuple(tieMetaHelper(std::get<Is>(std::forward<Tu>(tu)))...); return std::make_tuple(tieMetaHelper(std::get<Is>(std::forward<Tu>(tu)))...);
} }
@@ -297,7 +297,7 @@ namespace BlackMisc
private: private:
template <size_t I, class Tu> template <size_t I, class Tu>
static auto get_ref(Tu &&tu) -> decltype(tieHelper(std::get<I>(std::forward<Tu>(tu)))) static auto get_ref(Tu &&tu)
{ {
return tieHelper(std::get<I>(std::forward<Tu>(tu))); return tieHelper(std::get<I>(std::forward<Tu>(tu)));
} }

View File

@@ -191,18 +191,14 @@ namespace BlackMisc
//! If the derived class does not handle such requests, the signal can be ignored. //! If the derived class does not handle such requests, the signal can be ignored.
void valuesSaveRequested(const BlackMisc::CValueCachePacket &values); void valuesSaveRequested(const BlackMisc::CValueCachePacket &values);
private:
struct Element; // remove forward declaration (and uncomment the one below) when elementsStartingWith uses C++14 auto deduced return type
protected: protected:
//! Returns a range referring to all elements which start with the given prefix. //! Returns a range referring to all elements which start with the given prefix.
//! \todo Use C++14 auto deduced return type.
//! @{ //! @{
CRange<QMap<QString, QSharedPointer<Element>>::iterator> elementsStartingWith(const QString &keyPrefix) auto elementsStartingWith(const QString &keyPrefix)
{ {
return makeRange(m_elements.lowerBound(keyPrefix), m_elements.lowerBound(keyPrefix + QChar(QChar::LastValidCodePoint))); return makeRange(m_elements.lowerBound(keyPrefix), m_elements.lowerBound(keyPrefix + QChar(QChar::LastValidCodePoint)));
} }
CRange<QMap<QString, QSharedPointer<Element>>::const_iterator> elementsStartingWith(const QString &keyPrefix) const auto elementsStartingWith(const QString &keyPrefix) const
{ {
return makeRange(m_elements.lowerBound(keyPrefix), m_elements.lowerBound(keyPrefix + QChar(QChar::LastValidCodePoint))); return makeRange(m_elements.lowerBound(keyPrefix), m_elements.lowerBound(keyPrefix + QChar(QChar::LastValidCodePoint)));
} }
@@ -234,7 +230,7 @@ namespace BlackMisc
private: private:
friend class Private::CValuePage; friend class Private::CValuePage;
// struct Element; // to be uncommented when the forward declaration above elementsStartingWith is removed struct Element;
using ElementPtr = QSharedPointer<Element>; // QMap doesn't support move-only types using ElementPtr = QSharedPointer<Element>; // QMap doesn't support move-only types
QMap<QString, ElementPtr> m_elements; QMap<QString, ElementPtr> m_elements;