2015-07-29 1 views
1

Таким образом, в последней Visual Studio 2015 следующий код, кажется, больше не будет работать:Visual Studio 2015 с использованием лямбда в constexpr

template<class F> 
struct wrapper 
{ 
    constexpr wrapper() 
    {} 
}; 

template<typename T> 
constexpr typename std::remove_reference<T>::type *addr(T&& t) 
{ 
    return &t; 
} 

template<class F> 
constexpr wrapper<F> wrap(F*) 
{ 
    return wrapper<F>(); 
} 


const constexpr auto add_one = wrap(true ? nullptr : addr([](int x) 
{ 
    return x + 1; 
})); 

отчетов Visual Studio назад illegal initialization of 'constexpr' entity with a non-constant expression. Это использовалось для работы в кандидате на выпуск, но последняя сборка больше не работает (я использую версию 14.0.23107.0). Это должно работать (оно работает как в clang, так и в gcc).

К сожалению, Microsoft не позволяет мне сообщать об ошибках. Так кто-нибудь знает об обходном пути?

+0

Проблема не в том, что вы говорите. Изменить 'true? nullptr: addr (...) 'to' true? (void *) 0: addr (...) ', и он принимается, даже если он использует лямбда. (Я понимаю, что это препятствует тому, чтобы 'add_one' имел тип, который вы хотите, и я не предлагаю это как замену.) – hvd

+0

Если вы хотите сообщить об ошибках, попробуйте http://connect.microsoft.com/VisualStudio (о хорошо сказано: «У вас нет прав на отправку отзывов для этого соединения».) –

ответ

2

Итак, кажется, что в визуальной студии есть проблема с преобразованием указателей с constexpr, как указывал @hvd. Обходной путь, я нашел, я могу сделать это вместо этого:

template<class F> 
struct wrapper 
{ 
    constexpr wrapper() 
    {} 
}; 

struct wrapper_deduce 
{ 
    constexpr wrapper_deduce() 
    {} 
    template<class T> 
    constexpr operator wrapper<T>() const 
    { 
     return wrapper<T>(); 
    } 
}; 


template<class F> 
constexpr wrapper<F> wrap_direct(const F&) 
{ 
    return wrapper<F>(); 
} 


const constexpr auto add_one = true ? wrapper_deduce() : wrap_direct([](int x) 
{ 
    return x + 1; 
}); 
+0

Итак, вы хотите переменную 'constexpr' с типом' wrapper ', где'? '- это тип lambda, которая добавляет 1 к своему аргументу 'int', но никак не может (в рамках определенного поведения) создавать или запускать лямбда этого типа? – Yakk

+0

@Yakk Это Павел, который написал [Static Lambdas: Инициализация lambdas во время компиляции] (http://pfultz2.com/blog/2014/09/02/static-lambda/), используя 'return reinterpret_cast (* this) (std: forward (xs) ...); '. Это не гарантированно работает, это точно, но у него есть 'static_assert', который, мы надеемся, обнаружит любые проблемные реализации. Во многих реализациях будет определено поведение: для типов с тривиальной инициализацией (которая, по общему признанию, не совсем то, что проверяется), допустимо вызывать экземпляры экземпляра без фактического построения экземпляра этого типа. – hvd

+0

@hvd Каким образом это лучше, чем функция, называемая 'add_one'? – Yakk