简体   繁体   中英

C++ templated class default constructor fails

So I am creating a Stack class for an assignment in C++. The core of the assignment is to familiarize us with templates. I have read my book over and over and looked question after question on here.

I need to have my Stack class be able to be constructed by

Stack s2;

but I get an error when I compile my test.cpp and can only compile when i construct as

Stack<T> s1;

where T is a std::string , int , etc. How do build my Stack so I can use both constructors?


Stack.cpp

#include <iostream>
#include <vector>
#include <stdlib.h>
#include <string>

using namespace std;

template<typename T> 
class Stack {
public:
    Stack();
    void Push(T val);
    T Pop();
    void Print();

private:
    vector<T> vecT;
};

template <typename T>
Stack<T>::Stack() { }

template <typename T>
void Stack<T>::Push(T val) { vecT.push_back(val); }

template <typename T>
T Stack<T>::Pop() { vecT.pop_back(); }

template <typename T>
void Stack<T>::Print() {
    cout << "[ ";
    for(int i=0; i<vecT.size(); i++) {
        cout << vecT[i] << " ";
    }
    cout << "]";
}

test.cpp

#include <iostream>
#include <vector>
#include <stdlib.h>
#include <string>

#include "Stack.cpp"

using namespace std;

int main() {
    Stack<string> s1;
        s1.Push("values1");
        s1.Push("values2");
        s1.Print();

    Stack s2;
        s2.Push("values1");
        s2.Push("values2");
        s2.Print();
}

What about a default template parameter?

template<typename T = std::string> 
class Stack {

Anyway, with

Stack<T> s1;

and

Stack s2;

you're not using different constructors; you're using, in both cases, the same default (no arguments) constructor.

Instead of templating everything you could just use a stack of a variant type (since C++17, before use Boost.Variant ). With the code below you can now push int , double , and std::string onto the stack. Furthermore, Pop() is missing a return statement. Also, pop_back() of vector returns nothing.

#include <iostream>
#include <vector>
#include <string>
#include <variant>

class Stack {
    using Variant = std::variant<int,double,std::string>;
public:
    Stack();
    void Push(Variant val);
    void Pop();
    void Print();

private:
    std::vector<Variant> vecT;
};

Stack::Stack() : vecT() {}

void Stack::Push(Variant val) { vecT.push_back(val); }

void Stack::Pop() { vecT.pop_back(); }

void Stack::Print() {
    std::cout << "[ ";
    for ( auto const& v : vecT )
        std::visit([] (auto&& arg) { std::cout << arg << " "; }, v);
    std::cout << "]\n";
}

int main() {
    Stack s1;
        s1.Push("values1");
        s1.Push("values2");
        s1.Print();

    Stack s2;
        s2.Push("values1");
        s2.Push("values2");
        s2.Print();
}

With Boost.Variant you get a C++98 compatible solution.

#include <iostream>
#include <vector>
#include <string>
#include <boost/variant.hpp>

class Stack {
    typedef boost::variant<int,double,std::string> Variant;
    typedef std::vector<Variant>::iterator Iterator;

    std::vector<Variant> vecT;

    struct visitor : public boost::static_visitor<void>
    {
        template < typename T >
        void operator()(T const& arg) const { std::cout << arg << " "; }
    };
public:
    Stack();
    void Push(Variant val);
    void Pop();
    void Print();
};

Stack::Stack() : vecT() {}

void Stack::Push(Variant val) { vecT.push_back(val); }

void Stack::Pop() { vecT.pop_back(); }

void Stack::Print() {
    std::cout << "[ ";
    for ( Iterator it = vecT.begin(); it != vecT.end(); ++it )
        boost::apply_visitor( visitor(), *it );
    std::cout << "]\n";
}

int main() {
    Stack s1;
        s1.Push("values1");
        s1.Push("values2");
        s1.Print();

    Stack s2;
        s2.Push("values1");
        s2.Push("values2");
        s2.Print();
}

You could use a default template parameter:

template<typename T = int> 
class Stack {

Then you could construct using:

Stack<> s2;

Also, the constructors are identical, you aren't calling a different one each time, but rather the template argument differs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM