エンジンによってパラメーター化されたstruct
テンプレートS
があるとします。
template<class Engine> struct S;
私は2つのエンジンを持っています:constexpr
メンバー関数を持つ「静的」エンジンsize()
と非constexpr
メンバー関数を持つ「動的」エンジンsize()
:
struct Static_engine {
static constexpr std::size_t size() {
return 11;
}
};
struct Dynamic_engine {
std::size_t size() const {
return size_;
}
std::size_t size_ = 22;
};
私が定義するsize()
にはメンバ関数S
として使用することができるconstexpr
エンジンのがあればsize()
ですがconstexpr
。私は書きます:
template<class Engine>
struct S {
constexpr std::size_t size() const {
return engine_.size();
}
Engine engine_;
};
次に、次のコードがGCC、Clang、MSVC、およびICCでコンパイルされます。
S<Static_engine> sta; // not constexpr
S<Dynamic_engine> dyn;
constexpr auto size_sta = sta.size();
const auto size_dyn = dyn.size();
の複雑さconstexpr
とさまざまな「不正な形式、診断は不要」を考慮に入れると、私はまだ疑問があります。このコードは整形式ですか?
(このコードの有効性がこれら2つの標準で異なる場合に備えて、この質問にc ++ 17とc ++ 20の両方のタグを付けました。)
コードは書かれているとおりに問題ありません。
[dcl.constexpr]
6 constexpr関数テンプレートまたはクラステンプレートのメンバー関数のインスタンス化されたテンプレート特殊化がconstexpr関数またはconstexprコンストラクターの要件を満たさない場合、そのような特殊化は、そのような呼び出しがあったとしても、constexpr関数またはconstexprコンストラクターのままです。関数を定数式に含めることはできません。テンプレートの特殊化が、非テンプレート関数またはコンストラクターと見なされたときにconstexpr関数またはconstexprコンストラクターの要件を満たさない場合、テンプレートは形式が正しくなく、診断は必要ありません。
メンバーはDynamic_engine
、を使用する特殊化の定数式に表示されない場合がありますが、上記の段落で詳しく説明しているように、S::size
不正な形式にはなりません。また、有効なインスタンス化が可能であるため、NDRの不正な領域からはほど遠いです。Static_engine
代表的な例です。
引用は、最後のC ++ 17標準ドラフトであるn4659からのものであり、同様の表現が最新のC ++ 20ドラフトに表示されます。
sta.size()
定数式としての評価については、[expr.const]のリストを調べても、評価自体で許可されていないものは見つかりません。したがって、これは有効な定数式です(リストに無効なものが示されているため)。以下のために、一般的にconstexpr
機能が有効であるために、ただ存在することが必要であるいくつかの評価が有効な定数式を生成するために引数のセットを。次の例のフォームが示すように、標準は次のことを示しています。
constexpr int f(bool b)
{ return b ? throw 0 : 0; } // OK
constexpr int f() { return f(true); } // ill-formed, no diagnostic required
struct B {
constexpr B(int x) : i(0) { } // x is unused
int i;
};
int global;
struct D : B {
constexpr D() : B(global) { } // ill-formed, no diagnostic required
// lvalue-to-rvalue conversion on non-constant global
};
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加