C++03. Test for rvalue-vs-lvalue at compile-time, not just at runtime

前端 未结 2 2000
耶瑟儿~
耶瑟儿~ 2020-12-08 20:46

In C++03, Boost\'s Foreach, using this interesting technique, can detect at run-time whether an expression is an lvalue or an rvalue. (I found that via this StackOv

2条回答
  •  时光说笑
    2020-12-08 21:05

    It took some effort, but here's a tested and working is_lvalue macro that correctly handles const struct S function return types. It relies on const struct S rvalues not binding to const volatile struct S&, while const struct S lvalues do.

    #include 
    
    template 
    struct nondeducible
    {
      typedef T type;
    };
    
    char (& is_lvalue_helper(...))[1];
    
    template 
    char (& is_lvalue_helper(T&, typename nondeducible::type))[2];
    
    #define is_lvalue(x) (sizeof(is_lvalue_helper((x),(x))) == 2)
    
    struct S
    {
      int i;
    };
    
    template 
    void test_()
    {
      T a = {0};
      T& b = a;
      T (* c)() = 0;
      T& (* d)() = 0;
      assert (is_lvalue(a));
      assert (is_lvalue(b));
      assert (!is_lvalue(c()));
      assert (is_lvalue(d()));
    }
    
    template 
    void test()
    {
      test_();
      test_();
      test_();
      test_();
    }
    
    int main()
    {
      test();
      test();
    }
    

    Edit: unnecessary extra parameter removed, thanks Xeo.

    Edit again: As per the comments, this works with GCC but relies on unspecified behaviour in C++03 (it's valid C++11) and fails some other compilers. Extra parameter restored, which makes it work in more cases. const class rvalues give a hard error on some compilers, and give the correct result (false) on others.

提交回复
热议问题