7

タプル要素のオフセットを取得するために次のコードを書きました

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));
    }

これは実際には、offsetofマクロの実装に似ています。見栄えは悪いですが、コンパイルして 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;

「1000」を出力します。

私は constexpr についてあまり知らないので、私の質問は次のとおりです。

  1. それは合法的なc ++ですか?
  2. さらに重要なのは、constexpr 関数内で std::get (constexpr ではない) を呼び出すことが許可されているのはなぜですか?

私が constexpr を理解している限り、コンパイラはコンパイル時に式の結果を評価することを強制されるため、実際にはゼロ参照解除は発生しません。

4

1 に答える 1

5

合法的な C++ ですか?

「法的」という言葉が「整形式」を意味する場合、その通りです。

「合法的」とは、「有効であり、任意のコンパイラおよび標準ライブラリの実装で動作する」という意味である場合、std::tuplePOD ではないため、いいえ。

関数内でstd::get(ではない)を呼び出すことが許可されているのはなぜですか?constexprconstexpr

基本的に、constexpr関数は必ずしも定数式だけで構成されている必要はありません。関数を定数式で使用しようとするとtuple_element_offset()、コンパイル エラーが発生します。

関数は、ある状況では定数式で使用できるが、別の状況では使用できないという考えがあるため、constexpr関数を常に定数式で使用できなければならないという制限はありません (そのような制限がないため、関数の場合のように、特定のconstexpr関数が定数式で使用できない可能性もあります)。

C++0x ドラフトには良い例があります (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);
于 2011-03-18T23:14:52.080 に答える