I'm trying to use a requires
clause, and it only works if used on an actual concrete object passed as an argument to a function, but not one given by declval
:
struct ImageMipInfo
{
ImageMipInfo() {}
ImageMipInfo(int a)
{}
static inline constexpr int JUST_SERIALISE_ME_BY_MEMCPYING{};
};
template <typename T>
static constexpr bool isTypeMemcopyableUsingArgumentObject(T& arg)
{
constexpr bool bHasMemcpyOverride = requires { arg.JUST_SERIALISE_ME_BY_MEMCPYING; };
return bHasMemcpyOverride;
}
template <typename T>
static constexpr bool isTypeMemcopyableUsingDeclVal()
{
constexpr bool bHasMemcpyOverride = requires { declval<T>().JUST_SERIALISE_ME_BY_MEMCPYING; };
return bHasMemcpyOverride;
}
int main() {
ImageMipInfo mip_info;
static_assert(isTypeMemcopyableUsingArgumentObject(mip_info)); // This passes
static_assert(isTypeMemcopyableUsingDeclVal<ImageMipInfo>()); // This doesn't pass
}
The error I get on Clang is:
error: static assertion failed due to requirement
And in GCC:
error: there are no arguments to 'declval' that depend on a template parameter, so a declaration of 'declval' must be available
You believe the expression declval<ImageMipInfo>().JUST_SERIALISE_ME_BY_MEMCPYING;
is well-formed, and therefore the requires
clause should be true.
Let's put that expression directly in main()
, to force the compiler to describe what might be wrong!
int main()
{
declval<ImageMipInfo>().JUST_SERIALISE_ME_BY_MEMCPYING;
}
In function 'int main()':
error: 'declval' was not declared in this scope; did you mean 'std::declval'?
| declval<ImageMipInfo>().JUST_SERIALISE_ME_BY_MEMCPYING;
| ^~~~~~~~~~~~~~~~~~~~~
| std::declval
The correct spelling is std::declval
, which is defined in header <utility>
.
Your requires clause fails because declval
is not defined in your code, which makes declval<T>().JUST_SERIALISE_ME_BY_MEMCPYING;
ill-formed.
#include <utility>
struct ImageMipInfo
{
ImageMipInfo() {}
ImageMipInfo(int a)
{}
static inline constexpr int JUST_SERIALISE_ME_BY_MEMCPYING{};
};
template <typename T>
static constexpr bool isTypeMemcopyableUsingArgumentObject(T& arg)
{
constexpr bool bHasMemcpyOverride = requires { arg.JUST_SERIALISE_ME_BY_MEMCPYING; };
return bHasMemcpyOverride;
}
template <typename T>
static constexpr bool isTypeMemcopyableUsingDeclVal()
{
constexpr bool bHasMemcpyOverride = requires { std::declval<T>().JUST_SERIALISE_ME_BY_MEMCPYING; };
return bHasMemcpyOverride;
}
int main() {
ImageMipInfo mip_info;
static_assert(isTypeMemcopyableUsingArgumentObject(mip_info)); // This passes
static_assert(isTypeMemcopyableUsingDeclVal<ImageMipInfo>()); // This DOES PASS NOW
}