Could anyone hint me why this code fails to compile with error?
g.cpp: In lambda function:
g.cpp:66:36: error: inconsistent types ‘bool’ and ‘std::_Bit_reference’ deduced for lambda return type
66 | return was[n - 1][m - 1];
If i explicitely do
const auto bfs = [&](int del) -> bool {
it compiles ok.
code
#include<bits/stdc++.h>
using namespace std;
void __print(int x) {cerr << x;}
void __print(long x) {cerr << x;}
void __print(long long x) {cerr << x;}
void __print(unsigned x) {cerr << x;}
void __print(unsigned long x) {cerr << x;}
void __print(unsigned long long x) {cerr << x;}
void __print(float x) {cerr << x;}
void __print(double x) {cerr << x;}
void __print(long double x) {cerr << x;}
void __print(char x) {cerr << '\'' << x << '\'';}
void __print(const char *x) {cerr << '\"' << x << '\"';}
void __print(const string &x) {cerr << '\"' << x << '\"';}
void __print(bool x) {cerr << (x ? "true" : "false");}
template<typename T, typename V>
void __print(const pair<T, V> &x) {cerr << '{'; __print(x.first); cerr << ", "; __print(x.second); cerr << '}';}
template<typename T>
void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? ", " : ""), __print(i); cerr << "}";}
void _print() {cerr << "]\n";}
template <typename T, typename... V>
void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
#ifndef ONLINE_JUDGE
#define dbg(x...) cerr << "\e[91m"<<__func__<<":"<<__LINE__<<" [" << #x << "] = ["; _print(x); cerr << "\e[39m" << endl;
#else
#define dbg(x...)
#endif
int main() {
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
#endif
cin.tie(0)->sync_with_stdio(0);
int nsc;
cin >> nsc;
for(int sc = 0; sc < nsc; sc++) {
int n, m;
cin >> n >> m;
vector<vector<int>> a(n, vector<int>(m));
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
cin >> a[i][j];
vector<vector<bool>> was(n, vector<bool>(m, false));
const auto bfs = [&](int del) {
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
was[i][j] = false;
was[0][0] = true;
for(int j = 1; j < m; j++)
was[0][j] = (a[0][j] % del == 0 && was[0][j-1]);
for(int i = 1; i < n; i++){
bool some = false;
for(int j = 0; j < m; j++)
if (a[i][j] % del == 0) {
was[i][j] = was[i - 1][j];
if (j > 0)
was[i][j] = was[i][j] || was[i][j - 1];
some = some || was[i][j];
}
if (!some) return false;
// cout << "dbg " << i << " " << j << " " << was[i][j] << "\n";
}
return was[n - 1][m - 1];
};
int res = 1;
for(int i = 1; i * i <= a[0][0]; i++)
if (a[0][0] % i == 0) {
if (bfs(a[0][0] / i)) {
res = max(res, a[0][0] / i);
break;
}
if (bfs(i))
res = max(res, i);
}
cout << res << "\n";
}
return 0;
}
Auto comment: topic has been updated by Alexey (previous revision, new revision, compare).
It fails due to different types of values returned from the lambda. If you specify the type explicitly, the return values are casted to it.
Note also that
vector<bool>::operator []
returns proxy objects, not booleans.as it says here it should return reference to an elemnt, bool& in my case https://en.cppreference.com/w/cpp/container/vector/operator_at
The
vector
class has specialization forbool
s.reference in the case of
vector<bool>
is like that.dude, thanks a lot, you are right
vector<bool>
is a specialized and space-optimized version ofvector
class to store each value in a single bit rather than a byte. (8 bits in a byte)So when you access a value of
vector<bool>
, it returnsstd::_Bit_reference
rather thanbool
as you would expect.Now, return type of lambda should be consistent in every return statement. But in your code
return was[n - 1][m - 1];
has return typestd::_Bit_reference
and everywhere else it isbool
likereturn false;
When you do
const auto bfs = [&](int del) -> bool
, you cause explicit conversion to bool and therefore it is consistent and it compiles. You could also doreturn bool(was[n - 1][m - 1]);
and it would work.If you don't specify the return type of a lambda function, the return type in each
return
should be the exact same thing. For example, you can't have two returns like this:because one returns an
int
and the other returns along long
. The C++ compiler doesn't care that each return type can be implicitly cast to the other. The same thing is in your code.Actually, each
bool
takes up one byte, not just one bit. That's whystd::vector<bool>
doesn't have abool
array inside. Instead, it tries to save space by grouping many bool values into chunks, so that each byte can hold up to eight boolean values.So,
std::vector<bool>
can't really returnbool&
because there's nobool
inside the vector to return a reference to. Instead, it returnsstd::_Bit_reference
, which has some simple logic inside that lets you modify each bit in chunks.For a C++ compiler,
std::_Bit_reference
andbool
aren't the same type, so you can't return both of them in different parts of your lambda function. That's why you can't compile that code without explicitly specifying that you want the lambda to returnbool
.