2

私は関数を持っています:

template<class T>
static string
format(T ui, T sentinal, char listSeparator)
{
    stringstream s;
    if (ui == sentinal)
    {
        s << "n/a" << listSeparator;
    }
    else
    {
        s << ui << listSeparator;
    }
    return s.str();
}

関数が呼び出された方法は次のとおりです。

output << format(field1,Backend::NA_Value, csvSeparator);
output << format(field2,Backend::NA_Value, csvSeparator);
/// ...etc

以前 はfield1field2タイプはでしたunsigned int。これらのタイプをに変更することが決定されましたunsigned long long。しかし、コンパイルエラーが発生します:

std::string format(T,T,char)' : template parameter 'T' is ambiguous
main.cpp(39) : see declaration of 'format'
could be 'Juint'
'unsigned __int64'

その理由は何ですか?NA_Value?それは次のように定義されています:

static const Juint NA_Value = (Juint) -1;
typedef unsigned int   Juint

テンプレートTを判別できませんか?!コンパイラはどこから__int64について決定しますか?

4

3 に答える 3

3

これはテンプレートタイプの推定の問題であり、関数のシグネチャで同じタイプが複数回発生します。T呼び出しでは、2つのオカレンスが異なるタイプであるため、コンパイラーは2つのタイプのどちらになりたいかを認識しません。

formatあなたは次のように電話します(Juintあなたに応じて置き換えられますtypedef):

format(unsigned long long ui, unsigned int sentinal, char listSeparator);

前者の引数の型を変更したため、2番目の引数とは異なります。この変更を行う前は、両方のパラメーターのタイプは同じでした。

この問題を解決するには、次のオプションがあります。

  • テンプレートの種類を変えます。(Joachim Pileborgによる回答を参照)

  • 関数を呼び出すときにテンプレートパラメーターとして明示的に指定することにより、特定のタイプを強制します。これにより、通常の関数で慣れているように、一致しないパラメーターが自動的にキャストされます(この場合、型の推定は行われません)。

    output << format<Juint>(field2,Backend::NA_Value, csvSeparator);
                    ^^^^^^^
    
    output << format<unsigned long long>(field2,Backend::NA_Value, csvSeparator);
                    ^^^^^^^^^^^^^^^^^^^^
    
  • パラメータの1つを他のタイプにキャストします。これにより、両方のパラメーターが同じになり、型の推定が成功します。

    output << format(static_cast<Juint>(field2),Backend::NA_Value, csvSeparator);
                     ^^^^^^^^^^^^^^^^^^
    
    output << format(field2,static_cast<unsigned long long>(Backend::NA_Value), csvSeparator);
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    
  • のtypedefも変更してJuint、型が再び同じになり、型の推定も成功するようにします。

  • タイプ特性/を追加enable_ifします。これにより、テンプレートタイプは、条件を満たすタイプの特定のクラスに制限されますが、あなたの場合、これはあなたが望むものではないと思います。

個人的には、別のオプションがあればいいのにと思います。型の推定を最初のパラメーターでのみ実行し、2番目のパラメーターを呼び出しサイトに自動的にキャストするように強制する(「T推定しない」パラメーターのように)と便利です。タイプ)。しかし、そのようなオプションはありません。

あなたの場合の最良のオプションはJuint、同じタイプ(リストの4番目のオプション)にするか、最初のオプションを選択して関数を「より一般的」にすることです。Joachim Pileborgの回答で一般的に指摘されているように、関数内の型の使用法には注意が必要ですが、あなたの場合は、関数の本体を変更しなくても問題ありません。

于 2013-01-21T12:17:40.100 に答える
1

の型は、または変数Backend::NA_Valueと同じではなくなりました。1つはしばらくの間、もう1つはです。field1field2unsigned intunsigned long long

Juintのタイプに一致するようにtypedefを変更します。または、新しいテンプレート変数を追加できます。field1field2

template<class T, class U>
static string
format(T ui, U sentinal, char listSeparator)

もちろん、後者を実行すると、比較でタイプの不一致に関する他のエラーや警告が表示されます。

于 2013-01-21T12:17:59.013 に答える
1

コンパイラ エラーがすべてをT物語っています。unsigned long longで示されているとおりですかfield1、それとも でunsigned int示されているとおりBackend::NA_Valueですか?
コンパイラは何を意味しているのか判断できないため、エラーが発生します。

考えられる解決策は次のとおりです。

  1. 同様Backend::NA_Valueに変更unsigned long long
  2. 使用するタイプを明示的に指定しますT

    format<unsigned long long>(field1, Backend::NA_Value, csvSeparator);
    
  3. 1 番目と 2 番目の引数が異なる型になるように形式を変更します。

    template<class T, class U>
    static string
    format(T ui, U sentinal, char listSeparator)
    {
        stringstream s;
        if (ui == sentinal)
        {
            s << "n/a" << listSeparator;
        }
        else
        {
            s << ui << listSeparator;
        }
        return s.str();
    }
    

    この変更により、sentinalは と同等に比較できる任意の型にすることができますui

于 2013-01-21T12:26:16.930 に答える