get the offset of a tuple element

I have wrote the following code to get the offset of a tuple element

template<size_t Idx,class T>
 constexpr size_t tuple_element_offset() {
        return static_cast<size_t>(
                    reinterpret_cast<char*>(&std::get<Idx>(*reinterpret_cast<T*>(0))) - reinterpret_cast<char*>(0));
    }

This is actually similar to the implementation of the offsetof macro. It looks ugly, but compiles and works fine on gcc-4.6

typedef std::tuple<int,char,long> mytuple;

mytuple var = std::make_tuple(4,'c',1000);
char * ptr = reinterpret_cast<char*>(&var);
long * pt = reinterpret_cast<long*>(ptr+tuple_element_offset<2,mytuple>());

std::cout << *pt << std::endl;

prints "1000".

I don't know too much about constexpr, so my questions are:

  • Is it legal c++?
  • More important, why I am allowed to call std::get (which is non constexpr) inside a constexpr function?
  • As far as I understand constexpr, the compiler is forced to evaluate the result of the expression at compile time, so no zero-dereferentiation can occurs in practice.


    Is it legal C++?

    If by "legal" you mean "well-formed," then, yes.

    If by "legal" you mean "valid and will work on any compiler and Standard Library implementation, then, no, because std::tuple is not POD.

    Why I am allowed to call std::get (which is not constexpr ) inside a constexpr function?

    Basically, a constexpr function doesn't necessarily have to consist of just a constant expression. If you tried to use your tuple_element_offset() function in a constant expression, you'd get a compilation error.

    The idea is that a function might be usable in a constant expression in some circumstances but not in others, so there isn't a restriction that a constexpr function must always be usable in a constant expression (since there isn't such a restriction, it's also possible that a particular constexpr function might never be usable in a constant expression, as is the case with your function).

    The C++0x draft has a good example (from 5.19/2):

    constexpr const int* addr(const int& ir) { return &ir; } // OK
    
    // OK: (const int*)&(const int&)x is an address contant expression
    static const int x = 5;
    constexpr const int* xp = addr(x); 
    
    // Error, initializer for constexpr variable not a constant expression; 
    // (const int*)&(const int&)5 is not a constant expression because it takes
    // the address of a temporary
    constexpr const int* tp = addr(5);
    
    链接地址: http://www.djcxy.com/p/66590.html

    上一篇: C ++

    下一篇: 获取元组元素的偏移量