У меня проблема с "if constexpr" в шаблонной лямбда. Для аргумента пусть игнорирует, как я туда попал, но у меня есть структура foo, которая каким-то образом определяется следующим образом:
template<bool condition>
struct foo {
int a;
// Only contains b if condition is true
int b;
}
Теперь я могу определить шаблонную функцию thtemplate
template<bool condition>
void print_fun(foo & obj) {
/* Do something with obj.a */
if constexpr(condition)
/* Do something with obj.b */
};
Игнорирование этой функции и ее использование скомпилируется, если параметр constexpr в foo
совпадает с параметром print_fun
, т.е.
constexpr bool no = false;
foo<no> obj = {};
print_fun<no>(obj);
Это компилируется, потому что ложная ветвь отбрасывается внутри шаблонизированного объекта и, следовательно, нет проблем с использованием obj.b внутри print_fun.
Однако, если я определяю аналогичное лямбда-выражение следующим образом:
template<bool condition>
auto print_lambda = [](foo & obj) {
/* Do something with obj.a */
if constexpr(condition)
/* Do something with obj.b */
};
и создайте экземпляр:
constexpr bool no = false;
foo<no> obj = {};
print_lambda<no>(obj);
то ложная ветвь не отбрасывается, и компилятор дает мне
'b': не является членом 'foo'
Является ли это предполагаемым поведением, это происходит на других компиляторах? Я делаю что-то неправильно? Или это ошибка в компиляторе? (Microsoft Visual Studio версии 15.4.1, gcc 7.2)
Проверьте мой тест здесь с gcc, где он не компилируется для функтора или функции.
Изменить:
Вот код моего минимального примера, я не знал, что внешней ссылки не хватит. Это компилируется на Visual Studio 15.4.1, за исключением отмеченной строки.
foo_bar
заменяет foo
в моем описании.
#include <iostream>
constexpr bool no = false;
struct foo {
int x;
};
struct bar {
int y;
};
template <bool, typename AlwaysTy, typename ConditionalTy>
struct Combined : AlwaysTy {};
template <typename AlwaysTy, typename ConditionalTy>
struct Combined<true, AlwaysTy, ConditionalTy> : AlwaysTy, ConditionalTy {};
using foo_bar = Combined<no, foo, bar>;
template<bool condition>
void print_fun(foo_bar & obj) {
std::cout << obj.x << std::endl;
if constexpr(condition)
std::cout << obj.y << std::endl;
};
template<bool condition>
auto print_lambda = [](foo_bar & obj) {
std::cout << obj.x << std::endl;
if constexpr(condition)
std::cout << obj.y << std::endl;
};
int main(int argc, char ** argv) {
foo_bar obj = {};
print_lambda<no>(obj); // Does not compile
print_fun<no>(obj);
}