1

可変引数関数について読んsumで、任意の数値型の任意の数を受け入れ、それらの合計を計算する関数を見つけました。

この関数のテンプレート化された性質により、演算子は文字列に対して定義されているためstring、オブジェクトを受け入れると予想していました。+

#include <iostream>
#include <string>
#include <type_traits>
#include <utility>

using namespace std;

template <typename T> T sum(T && x)
{
    return std::forward<T>(x);
}

template <typename T, typename ...Args>
typename std::common_type<T, Args...>::type sum(T && x, Args &&... args)
{
    return std::forward<T>(x) + sum(std::forward<Args>(args)...);
}

int main()
{
    auto y = sum(1, 2, 4.5); // OK
    cout << y << endl;

    auto x = sum("Hello!", "World"); // Makes error
    cout << x << endl;

    return 0;
}

エラー:

タイプ 'const char [7]' および 'const char [6]' からバイナリ 'operator+' への無効なオペランド

Hello!私はそれが連結されてWorld出力されることを期待してい ましたHello!World。何が問題ですか?

4

2 に答える 2

2

根本的な問題は、可変個引数テンプレートではなく、期待どおりです-文字列リテラルなど"hello"は型ではありませんstd::string。それらは文字数 + 1 の型です。実際にそれらから (または最初の文字列からでも) 文字列を作成すると、期待どおりに動作しますchar const[N]N

// snip

int main()
{
    auto y = sum(1, 2, 4.5); // OK
    cout << y << endl;

    auto x = sum(std::string("Hello!"), "World"); // OK
    cout << x << endl;

    return 0;
}

実例。

于 2013-02-24T21:21:36.050 に答える
2

文字列リテラルはstd::stringオブジェクトではありません。operator +文字の配列にはNoが定義されています。

あなたのコンパイラがあなたに言っているように、"Hello!"has type const char[7]"World"has typeconst char[6]です。これらの型の 2 つの変数を宣言し、それらの合計を取得してみてください。

int main()
{
    char const a[7] = "Hello!";
    char const b[6] = "World";
    (a + b);
}

そして、コンパイラは同様のエラーを表示します:

error: invalid operands of types 'const char [7]' and 
       'const char [6]' to binary 'operator+'

コードを機能させるには、2 つの文字列リテラルの少なくとも 1 つをstd::stringオブジェクトにラップします (オブジェクトには、対応する 2 つのオーバーロードがoperator +存在しstd::stringます)。

auto x = sum(std::string("Hello!") + "World");

また:

auto x = sum("Hello!" + std::string("World"));

もちろん、両方の引数をラップすることもできますが、それは不要です。

于 2013-02-24T21:18:05.397 に答える