Как захватить тип возвращаемого значения функции, возвращающей лямбду? - PullRequest
2 голосов
/ 27 апреля 2019

Учитывая этот код:

template <class Func> class ScopeGuard
{
public:
    /** @param func function object to be executed in dtor
    */
    explicit ScopeGuard( Func && func ) : m_func( std::move(func) ) {}

    ~ScopeGuard()
    {
        if (m_bDismissed)
            return;
        m_func();
    }

    /** Dismisses the scope guard, i.e. the function won't
        be executed.
    */
    void dismiss() { m_bDismissed = true; }

private:
    // noncopyable until we have good reasons...
    ScopeGuard(const ScopeGuard&) = delete;
    ScopeGuard& operator=(const ScopeGuard&) = delete;

    Func m_func;
    bool m_bDismissed = false;
};

// Get functor for cleanup to use in FlagRestorationGuard
auto GetFlagRestorationGuard(bool& i_flagRef)
{
    return [&i_flagRef, resetVal = i_flagRef] { i_flagRef = resetVal; };
}

class FlagRestorationGuard : public ScopeGuard<decltype(GetFlagRestorationGuard(*(new bool)))>
{
public:
    FlagRestorationGuard( bool& i_flagRef, bool i_temporaryValue )
        : ScopeGuard(GetFlagRestorationGuard(i_flagRef))
    {
        i_flagRef = i_temporaryValue;
    }
};

Я получаю следующую ошибку при Apple Clang для GetFlagRestorationGuard(*(new bool)):

ошибка: выражение с побочными эффектами не действует в неоцененном контексте [-Werror, -Wunevaluated-expression]

Обратите внимание, что этот код собирается и отлично работает с MSVC 2017. Конечно, можно переписать все это, чтобы использовать структуру с operator()() вместо лямбды и функцию, возвращающую ее, но мне интересно, есть ли хороший способ использовать лямбду, подобную этой?

Ссылка для действующего кода:

Ссылка на сбой сборки:

Ответы [ 2 ]

4 голосов
/ 27 апреля 2019

Используйте std::declval с lvalue ссылкой на bool:

class FlagRestorationGuard :
    public ScopeGuard<decltype(GetFlagRestorationGuard(std::declval<bool&>()))>
{
    ...
};
2 голосов
/ 27 апреля 2019

Это предупреждение, которое вы видите; не ошибка Он предупреждает вас, что побочный эффект new bool (выделение памяти) не произойдет, потому что он находится в неоцененном контексте.

Чтобы избавиться от предупреждения, вместо использования *(new bool) в качестве аргумента-заполнителя в выражении decltype используйте std::declval<bool&>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...