10

C++ template non-type parameter type deductionという質問の問題の解決策を見つけようとしました。これには、f を呼び出すテンプレート パラメーターは含まれませんが、暗黙的にテンプレート パラメーターの正しい型が選択されます。

constexprは、関数にコンパイル時の定数のみが含まれ、コンパイル時に評価されることを保証する必要があるため(少なくともそれが私が考えていることです)、この問題の解決策になると思いました。だから私はこれを思いついた:

template <class T, T VALUE> void f() {}

//first i tried this:
template <class T> auto get_f(T t) -> decltype( &f<T,t> ) { return f<T,t>; }

//second try:
template <class T> constexpr void (&get_f( T t ))()  { return f<T,t>; }

int main()
{
    get_f(10)(); //gets correct f and calls it
}

最初のバージョンでは、次のエラーが生成されます。

error: use of parameter 't' outside function body

末尾の戻り値の型の decltype ステートメントでのパラメーターの使用は問題ないはずなので、これは本当に紛らわしいですか?

2 番目のバージョンでは、次のエラーが生成されます。

error: invalid initialization of non-const reference of type 'void (&)()' 
       from an rvalue of type '<unresolved overloaded function type>'

私は完全fget_f. を持っていない場合、この種のエラー メッセージが表示されることが予想されますconstexpr。それで、私は何をしているのかconstexpr、またはGCCのC ++ 0x実装にこの場合の欠陥がありますか?

GCC 4.6.2 を使用しています

4

1 に答える 1

5

constexpr は、関数にコンパイル時の定数のみが含まれ、コンパイル時に評価されることを保証する必要があるため (少なくともそれが私が考えていることです)、この問題の解決策になると思いました。

constexpr関数は定数式のコンテキストで使用できますが、1 つに制限されません。この点で、メタ関数や通常の関数とは異なります。整数の後継者を返す問題を考えてみましょう:

// Regular function
int f(int i)
{ return i + 1; }

// Regular metafunction
template<int I>
struct g {
    static constexpr auto value = I + 1;
};

// constexpr function
constexpr int h(int i)
{ return i + 1; }

// Then...
{
    // runtime context: the metafunction can't be used
    int i;
    std::cin >> i;

    f(i); // Okay
    g<i>::value; // Invalid
    h(i); // Okay

    // compile time context: the regular function can't be used
    char a[f(42)]; // Invalid
    char b[g<42>::value]; // Okay
    char c[h(42)]; // Okay
}

constexprには他の用途 (コンストラクタなど) がありますが、constexpr関数に関して言えば、これが要点です。一部の計算は両方で使用できるため、一部の関数は実行時コンテキストと定数コンテキストの両方で使用できる必要があります。がコンパイル時の定数なのか、 から抽出されたのi + 1かを計算することができます。istd::cin

これは、constexpr関数の本体内では、パラメーター自体が定数式ではないことを意味します。したがって、あなたが試みていることは不可能です。あなたの関数は処理できません

int i;
std::cin >> i;
get_f(i); // what's the return type?

違反はここで発生します:

constexpr auto get_f(T t)
-> decltype( &f<T,t> ) // <-

tは言語の規則に従って定数式ではないため (たとえ実際定数式のみを渡したとしても)、 の 2 番目のテンプレート パラメーターとして表示することはできませんf

(そして、より大きな図では、いいえ、関数テンプレートからの引数推定を使用して、非型パラメーターをクラステンプレートに便利に渡すことができないことを意味します。)

于 2011-07-18T23:58:48.427 に答える