67

constexprとして宣言された関数を実行時に呼び出すことができる可能性があるため、コンパイラは、コンパイル時と実行時のどちらで計算するかを決定する基準はどれですか。

template<typename base_t, typename expo_t>
constexpr base_t POW(base_t base, expo_t expo)
{
    return (expo != 0 )? base * POW(base, expo -1) : 1;
}

int main(int argc, char** argv)
{
    int i = 0;
    std::cin >> i;

    std::cout << POW(i, 2) << std::endl;
    return 0;
}

この場合、iはコンパイル時に不明です。これが、コンパイラがPOW()を実行時に呼び出される通常の関数として扱う理由である可能性があります。ただし、このダイナミックは、見た目は便利ですが、実用的ではない意味があります。たとえば、コンパイル時にconstexpr関数を計算してもらいたい場合があります。コンパイラは、コンパイル時にも機能するのに、代わりに通常の関数として処理することを決定します。よくある落とし穴はありますか?

4

2 に答える 2

96

constexprすべての引数が定数式で、結果が定数式でも使用される場合、関数コンパイル時に評価されます。定数式は、リテラル ( など42)、非型テンプレート引数 ( など)、N要素宣言 ( など、constexprで宣言された別の変数など) の場合があります。template<class T, size_t N> class array;enumBlueenum Color { Red, Blue, Green };

すべての引数が定数式であり、結果が定数式で使用されていない場合に評価される可能がありますが、それは実装次第です。

于 2013-01-09T23:25:17.970 に答える
23

定数式が必要な場合は、コンパイル時に関数を評価する必要があります。

これを保証する最も簡単な方法は、constexpr値を使用するか、またはstd::integral_constant:

constexpr auto result = POW(i, 2); // this should not compile since i is not a constant expression
std::cout << result << std::endl;

また:

std::cout << std::integral_constant<int, POW(i, 2)>::value << std::endl;

また

#define POW_C(base, power) (std::integral_constant<decltype(POW((base), (power)), POW((base), (power))>::value)

std::cout << POW_C(63, 2) << std::endl;

また

template<int base, int power>
struct POW_C {
  static constexpr int value = POW(base, power);
};

std::cout << POW_C<2, 63>::value << std::endl;
于 2013-01-09T23:24:48.840 に答える