通常、constexprには副作用がない必要があります。しかし、私は、スローされた例外のコンストラクタで副作用を使用することが可能であることを発見しました。このテクニックは、以下のプログラムで実証されているように、constexpr関数のassert()をエミュレートするために使用できます。constexprによってスローされた例外に副作用を使用することは合法ですか?
#include <iostream>
#include <cstdlib>
#include <stdexcept>
struct constexpr_precond_violated : std::logic_error
{
constexpr_precond_violated(const char* msg) :
std::logic_error(msg)
{
std::cerr << msg << '\n';
abort(); // to get a core dump
}
};
#define TO_STRING_IMPL(x) #x
#define TO_STRING(x) TO_STRING_IMPL(x)
#define CONSTEXPR_PRECOND(cond, value) \
((!(cond)) ? throw constexpr_precond_violated(\
"assertion: <" #cond "> failed (file: " \
__FILE__ ", line: " TO_STRING(__LINE__) ")") \
: (value))
constexpr int divide(int x, int y)
{
return CONSTEXPR_PRECOND(y != 0, x/y);
}
int main(int argc, char** argv)
{
// The compiler cannot know argc, so it must be evaluated at runtime.
// If argc is 2, the precondition is violated.
return divide(100, argc - 2);
}
g ++ 4.7.2とclang ++ 3.1でテストしました。前提条件が失敗すると、エラーの場所とコアダンプが表示されます。
./constexpr_assert some_arg
assertion: <y != 0> failed (file: constexpr_assert.cpp, line: 26)
Aborted (core dumped)
したがって、現在のコンパイラで動作しますが、正当なC++ 11ですか?
第2引数として 'divide()'にコンパイル時定数 '0'を指定するとどうなりますか? *コンパイラが "例外をスロー"していますか? :) –
static_assert(除算(1,0)> = 0、 "テスト"); は単にリターン除算(1、0)をコンパイルしないであろう。 はClangでコンパイルされ、実行時にのみ失敗します。 –
定数式と 'constexpr'関数を区別するように注意する必要があります。 "' 'constexpr'のようなものは副作用のないものでなければなりません"というのは不正確です。 'constexpr'をキーワードにすぎないものと考えてください(' static'が気になります)。 –