3

Ok so Im just learning templates for the first time and so I was toying around creating my own template class that mimics its underlying type which is a vector. Keep in mind that the call to push_back just calls the push_back method of the underlying vector.

vector<string> sV;
sV.push_back("ha");       //ok: converts from const char[3] to string

Foo<string> fS;
fS.push_back("ha");      //error: const char[3] does not match the argument list

Is there a way I can fix this? I just want my template to feel as natural as if I'm using the real thing.


EDIT : This is basically the body of the class

template <typename T> class FooPtr;
template <typename T>
class Foo{
    friend class FooPtr<T>;
public:
    Foo() {data->make_shared(vector<T>); }
#ifdef INITIALIZER_LIST
    Foo(initializer_list<T>);
#endif
    void push_back(T &t) { data->push_back(t); }
    void push_back(T &&t) { data->push_back(move(t)); }
    bool empty() { if (data->size() == 0) return true; }
    FooPtr<T> insert(size_t, T&);
    T& operator[](size_t);
    T& front();
    T& back();
    FooPtr<T> begin() { return FooPtr<T>(*this); }
    FooPtr<T> end() { return FooPtr<T>(*this, data->size()); }
    void pop_back() { data->pop_back(); }
    void pop_front() { data->pop_front; }
private:
    void check(const string&, size_t = 0);
    shared_ptr<vector<T>> data;
};
9
  • template <typename T> void Foo<&T>::push_back(T) template <typename T> void Foo<&&T>::push_back(move(T)) Does that answer? Commented Jan 30, 2014 at 6:18
  • 1
    @RudolphRedNose, That shouldn't compile in the first place. Commented Jan 30, 2014 at 6:19
  • Jsut for push_back(), please... Commented Jan 30, 2014 at 6:21
  • 1
    Unrelated (sorta): unless I'm not reading this right (a distinct possibility), that std::move(t) should be a std::forward<T>(t). Commented Jan 30, 2014 at 6:38
  • 1
    @WhozCraig don't you think the answers are wrong here? shouldn't void push_back(T &&t) be picked for his call? since during overload resolution the converting constructor of the std::string is called and the std::string hence formed is an rvalue? Commented Jan 30, 2014 at 7:23

4 Answers 4

6

A method that should be able to accept a string literal same way as a std::string object must have a signature

void foo( const std::string & arg )

Therefore, your Foo::push_back must be

void Foo::push_back( const T & arg )
Sign up to request clarification or add additional context in comments.

2 Comments

so simple... yet so brilliant.
@RudolphRedNose The Standard Library documentation is a rich hoard of information.
2

As you can see here http://www.cplusplus.com/reference/vector/vector/push_back/ the std::vector offers two methods for push_back which are overloaded.

One for const types and for non const types.

Your first push_back succeeds as the std::vector provides a function which can handle types like

 const char *

where const is the magic word. Your wrapper template just offers a push_back method with the signature

T & t

Extending your implementation with the following should solve your problem:

void push_back (const T& t) {data->push_back(t);}

Comments

0

You want to only try to convert const char* (NOT const char or char or another type of char) to string, otherwise you're trying to map an element to a STL-container/array of that element which is nonsense in C++.

2 Comments

Very cryptic, please explain and use standard English.
Yes,thanks, very much so. But I think OP's original problem was the missing const. Never mind.
0

I think your compiler is wrong. my reasoning is as follows

when you instantiate Foo with std::string the push_back member functions that are generated will be as follows

void push_back(std::string &t) { data->push_back(t); }           --1
void push_back(std::string &&t) { data->push_back(move(t)); }    --2

1 will be picked if the argument is a non-const lvalue expression of type std::string.
2 will be picked if the argument is a non-const rvalue expression of type std::string.

when you pass "ha" , user defined conversion in std::string kicks in and since the produced std::string (std::string("ha")) is an rvalue, 2 should be picked. even addition of const to 1 will not cause the 2 from not being picked.

a nice post from STL

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.