最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Why doesn't this requires clause return true when using declval? - Stack Overflow

programmeradmin1浏览0评论

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

Link on Godbolt

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

Link on Godbolt

Share Improve this question edited Mar 14 at 18:40 Remy Lebeau 601k36 gold badges507 silver badges851 bronze badges asked Mar 14 at 18:23 ZebrafishZebrafish 15k3 gold badges66 silver badges153 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 6

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
}

https://godbolt./z/r7EcbG7n8

发布评论

评论列表(0)

  1. 暂无评论