2

エラー

stack.cc:53:28: error: no matching function for call to ‘Stack<std::basic_string<char> >::push(std::string)’
stack.cc:53:28: note: candidate is:
stack.cc:32:11: note: Stack<T>& Stack<T>::push(T&) [with T = std::basic_string<char>]

stack.cc

#include<iostream>

template <typename T>
class Stack {
private:
    T* array_;
    int length_;
    T* last_;
    void expandArray();

public:
    Stack(int length = 8) {
        array_   = new T[length];
        length_  = length;
        last_    = array_;
    }

    Stack<T>& push(T&);
    T pop();
};

template<typename T>
void Stack<T>::expandArray() {
    T* array_temp = new T[length_ << 1];
    memcpy(array_temp, array_, length_);
    std::swap(array_, array_temp);
    delete[] array_temp;
    length_ <<= 1;
}

template<typename T>
Stack<T>& Stack<T>::push(T& data) {
    if (last_ == (array_ + length_ - 1)) {
        expandArray();
    }
    last_[0] = data;
    last_++;
    return *this;
}

template<typename T>
T Stack<T>::pop() {
    if(array_ != last_) {
        T temp = last_[0];
        last_--;
        return temp;
    }
    return NULL;
}

int main() {
    Stack<std::string> s;
    s.push(std::string("a"))
     .push(std::string("b"))
     .push(std::string("c"))
     .push(std::string("d"));
    std::cout << s.pop() << std::endl;
    std::cout << s.pop() << std::endl;
    std::cout << s.pop() << std::endl;
    std::cout << s.pop() << std::endl;
}

std::stringからへの変換が行われている理由を理解したいstd::basic_string<char>ですか?

コードの品質についてもお気軽にコメントしてください。

4

3 に答える 3

7

実際の問題は、変数に格納されているのではなく、引数で作成されたオブジェクトへの参照を渡そうとしていることです。?へのそのT&議論を参照してください 非参照Stack<T>::pushであるため、ここで一時的なものを渡すことはできません。const次のようにしてみてください...

Stack<T>& push(const T&);

実装にもこの署名を使用してください。


そうは言っても、それstd::stringは単なるtypedefであることがわかりますstd::basic_string<char>。これは、文字列の機能を他の文字タイプ(std::wstringfor wchar_tstd::u16stringfor char16_t、およびstd::u32stringfor )にも拡張できるためchar32_tです。;-)

C++11仕様の§21.4クラステンプレートbasic_string[basic.string]を参照してください。

// basic_string typedef names
typedef basic_string<char> string;
typedef basic_string<char16_t> u16string;
typedef basic_string<char32_t> u32string;
typedef basic_string<wchar_t> wstring;

iostreamあなたがあなたのために含めることに頼るべきではないことに注意してstringください。cstringまた、通話のスコープを含めて指定する必要がありますmemcpy


ちなみに、コンストラクタの初期化子リストの使用を実際に検討する必要がありますStack...次のように参照してください。

Stack(int length = 8) : length_(length), array_(new T[length]), last_(array_) { }

array_これは、クラスメンバー宣言として先行するときに適切に機能することに注意してくださいlast_;-)


...そして最後のメモ。要素を先頭を超えpopて返すため、は正しくありません。代わりに、次のようにしてみてください...

template<typename T>
T Stack<T>::pop() {
    if (array_ != last_) {
        return *--last_;
    }
    /* other stuff here */
}

ポイントがトップを超えているため、逆参照するにデクリメントする必要があります。ちなみに、あなたはそのように避けたいと言ったとしても、 fromlast_のコピーを返しています。std::stringpop

NULLこれはポインタ型ではないため、戻ってはいけないことに注意してください。std::string実際、...をとるコンストラクターを介して作成するだけconst char *です。これは、の場合は明示的に禁止されていNULLます。§21.4.2¶8-9を参照してください...

basic_string(const charT* s, const Allocator& a = Allocator());

必要なもの: s nullポインタであってはなりません。

于 2012-09-15T03:14:06.207 に答える
1

std::stringstd::basic_string<char>変換されていないため、typedefです。その理由は、同じstd::basic_stringテンプレートを使用しwchar_tてユニコード文字列を使用できるためです。

于 2012-09-15T03:11:30.657 に答える
1

それがstd::string実際のところだからです-それは`std:: basic_string'の単なるエイリアスです:

typedef basic_string<char> string;

コンパイラがエラーメッセージを報告しているときは、エイリアス名ではなく、typedefの実際の基本型が表示されています。

于 2012-09-15T03:14:28.370 に答える