Closed hmoffatt closed 1 year ago
This is indeed odd. Looking at the code on ...\include\kdalgorithms\bits\transform.h(82,19), I see that it is evaluating the requirements of this function:
template <typename InputContainer, typename Transform> auto transformed(InputContainer &&input, Transform &&transform)
if __cplusplus >= 202002L
requires std::is_invocable_v<Transform, ValueType<InputContainer>>
endif
but the type you provide as the first template argument (QJsonArray) would make the first argument provided (QVector< S >) not match in the first place, and it should discard this version.
Sorry, this is beyond me.
It works with the compiler set to c++17, but not c++20 or c++2a, which confirms that code is firing. Although I don't understand why it would compile just by removing that is_invocable_v test.
But why is it trying that version of transformed() anyway? It should be the version at line 91 with a different ResultContainer type, since I have explicitly specified a different result container than the input container.
This change has not solved my Visual Studio compile errors. The problem cases are all when the output container is QJsonArray.
Adding the /Zc:__cplusplus
compile flag fixes the build for me. See here for more details.
PR #47 will make adding the flag unnecessary once merged.
Adding the
/Zc:__cplusplus
compile flag fixes the build for me. See here for more details.
I'm afraid it doesn't fix it for me - the code in my report still does not compile. (In fact, qmake in Qt 5.15.12 already enabled that switch for me.)
However if I replace the
const auto& v
parameter in the lambda withconst S& v
then it does compile.
It also works if I specify the return type of the lambda explicitly:
void f()
{
struct S { int a, b; };
QVector<S> s;
auto j = kdalgorithms::transformed<QJsonArray>(s, [](const auto& v) -> QJsonObject
{
return QJsonObject{
{ QStringLiteral("a"), v.a },
{ QStringLiteral("b"), v.b }
};
});
}
I also have a similar problem using filtered_transform
; weirdly, I can use auto
for the transform but not the filter. This compiles:
class ContentItem
{
public:
int num = 0;
int attempt_num = 0;
QDateTime purchased;
QDateTime expires;
};
QVector<ContentItem> user_courses;
auto x = kdalgorithms::filtered_transformed<std::vector<int>>(user_courses,
[](const auto& item) { return item.num; },
[expiry](const ContentItem& item) { return item.expires.isNull() || item.expires >= expiry; });
But using auto
in the filter makes it fail:
auto x = kdalgorithms::filtered_transformed<std::vector<int>>(user_courses,
[](const auto& item) { return item.num; },
[expiry](const auto& item) { return item.expires.isNull() || item.expires >= expiry; });
with error:
1>test.cpp(2685,44): error C2228: left of '.expires' must have class/struct/union
1>test.cpp(2685,44): message : type is 'const _T1'
1> with
1> [
1> _T1=int
1> ]
1>C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.34.31933\include\type_traits(1470,1): message : see reference to function template instantiation 'auto TUser::currentCourseLicences::<lambda_2>::operator ()<_Ty1>(const _T1 &) const' being compiled
1> with
1> [
1> _Ty1=int,
1> _T1=int
1> ]
1>C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.34.31933\include\type_traits(1675,38): message : see reference to alias template instantiation 'std::_Decltype_invoke_nonzero<TUser::currentCourseLicences::<lambda_2>,int,>' being compiled
1>C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.34.31933\include\type_traits(1748,42): message : see reference to alias template instantiation 'std::_Is_invocable_r_<bool,TUser::currentCourseLicences::<lambda_2>,int>' being compiled
1>include\kdalgorithms\bits\shared.h(74,10): message : see reference to variable template 'const bool is_invocable_r_v<bool,`TUser::currentCourseLicences'::`2'::<lambda_2>,int>' being compiled
1>include\kdalgorithms\bits\transform.h(196,14): message : see reference to variable template 'bool UnaryPredicateOnContainerValues<`TUser::currentCourseLicences'::`2'::<lambda_2>,std::vector<int,std::allocator<int> > >' being compiled
Again adding the return types for the lambda makes it compile:
auto x = kdalgorithms::filtered_transformed<std::vector<int>>(user_courses,
[](const auto& item) -> int { return item.num; },
[expiry](const auto& item) -> bool { return item.expires.isNull() || item.expires >= expiry; });
Indeed, the issue with /Zc:__cplusplus
was there but it was unrelated.
I managed to reproduce your error with /std:c++latest
(but not with /std:c++20
somehow).
My impression is that when concepts are introduced that error is legitimate because the requirement that the lambda is invocable with the valuetype or QJsonArray
is met (type-wise auto can be replaced with QJsonValue
just fine, and the body of the lambda is not taken into account with std::is_invocable
). That would explain why it does work when you switch from auto
to S
.
Will have to dig a bit more to figure out more details.
I managed to reproduce your error with
/std:c++latest
(but not with/std:c++20
somehow).
Odd, I have only /std:c++20, not c++latest. Visual Studio 17.4.4 (2022).
Is there another change other than the /Zc:__cplusplus
switch? Because as I wrote above I still have the problem and I thought you were able to reproduce it also.
I'm using into a QJsonArray of QJsonObjects as per the code below. It compiles OK with g++ 10 and clang++ 11, but not in Visual Studio 2022.
transformed
to convert a QVectorThe VS compiler reports
However if I replace the
const auto& v
parameter in the lambda withconst S& v
then it does compile.It seems that with auto a QJsonValue is being passed, being the output container's value_type perhaps?