constexpr
functions には以下が含まれていません:
非リテラル型の変数の定義
しかし、この回答ではラムダは1つで定義されています: https://stackoverflow.com/a/41616651/2642059
template <typename T>
constexpr auto make_div(const T quot, const T rem)
{
return [&]() {
decltype(std::div(quot, rem)) result;
result.quot = quot;
result.rem = rem;
return result;
}();
}
私のコメントでは、div_t
を1つに定義しています: div_tオブジェクトを初期化するにはどうすればよいですか?
template <typename T>
constexpr decltype(div(T{}, T{})) make_div(const T quot, const T rem)
{
decltype(div(T{}, T{})) x{};
x.quot = quot;
x.rem = rem;
return x;
}
「非リテラル型の変数の定義」の禁止は、正確にはどういう意味ですか?
Visual Studio 2015ではdiv_t
の定義を許可していませんが、そのような不正な動作をラムダでラップして実行することは許容されているので、無意味だと思います。どちらかのコンパイラがdiv_t
の定義に関して正しく動作しているかどうかを知りたいのですが。
Visual Studio 2015は c ++ 14 の拡張子constexpr
: https: //msdn.Microsoft.com/en-us/library/hh567368.aspx#C-14-Core-Language-Features
constexpr
関数関数の本文にはのみを含めることができます。
- nullステートメント(プレーンセミコロン)
- _
static_assert
_宣言- クラスまたは列挙を定義しない
typedef
宣言およびエイリアス宣言using
宣言using
ディレクティブ- 正確に1つの
return
ステートメント
したがって c ++ 11 はdecltype(div(T{}, T{})) x{}
の定義を許容できません。ただし、同じ結果を得るには、constexpr
関数で推奨される3項 here をロールしてもかまいません。
_template <typename T>
constexpr auto make_div(const T quot, const T rem)
{
using foo = decltype(div(T{}, T{}));
return foo{1, 0}.quot != 0 ? foo{quot, rem} : foo{rem, quot};
}
_
constexpr
関数関数本体には、以外のものが含まれる場合があります:
- asm宣言
- gotoステートメント
- caseおよびdefault以外のラベルを持つステートメント
- トライブロック
- 非リテラル型の変数の定義
- 静的またはスレッドストレージ期間の変数の定義
- 初期化が実行されない変数の定義
"リテラルタイプ"が定義されている場合 ここ 、特にオブジェクトの場合は、それらは自明なデストラクタを持つ集約タイプである可能性があります。したがって、_div_t
_は間違いなく適格です。したがって c ++ 14 、および拡張gccにより、decltype(div(T{}, T{})) x{}
の定義を許容できます。
constexpr
関数C++ 17では、「リテラルタイプ」の定義にクロージャタイプのサポートが追加されたため、gccとVisual Studioの両方がreturn
ステートメントでのラムダの使用をサポートしているのは奇妙です。それは前向きなサポートか、コンパイラがラムダをインライン化することを選択したかのどちらかだと思います。どちらの場合でも、 c ++ 14constexpr
関数としての資格があるとは思いません。
[ ソース ]