Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a templated parameter's value_type

Tags:

c++

std

templates

How is one supposed to use a std container's value_type?
I tried to use it like so:

#include <vector>

using namespace std;

template <typename T>
class TSContainer {
private:
        T container;
public:
        void push(T::value_type& item)
        {
                container.push_back(item);
        }
        T::value_type pop()
        {
                T::value_type item = container.pop_front();
                return item;
        }
};
int main()
{
        int i = 1;
        TSContainer<vector<int> > tsc;
        tsc.push(i);
        int v = tsc.pop();
}

But this results in:

prog.cpp:10: error: ‘T::value_type’ is not a type
prog.cpp:14: error: type ‘T’ is not derived from type ‘TSContainer<T>’
prog.cpp:14: error: expected ‘;’ before ‘pop’
prog.cpp:19: error: expected `;' before ‘}’ token
prog.cpp: In function ‘int main()’:
prog.cpp:25: error: ‘class TSContainer<std::vector<int, std::allocator<int> > >’ has no member named ‘pop’
prog.cpp:25: warning: unused variable ‘v’

I thought this was what ::value_type was for?

like image 505
Jonathan Winks Avatar asked Nov 09 '11 23:11

Jonathan Winks


People also ask

What is the purpose of template parameter?

A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.

Can we pass Nontype parameters to templates?

Template classes and functions can make use of another kind of template parameter known as a non-type parameter. A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument.

What are template parameters?

In UML models, template parameters are formal parameters that once bound to actual values, called template arguments, make templates usable model elements. You can use template parameters to create general definitions of particular types of template.

Can a template be a template parameter?

A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)


3 Answers

You have to use typename:

typename T::value_type pop()

and so on.

The reason is that the compiler cannot know whether T::value_type is a type of a member variable (nobody hinders you from defining a type struct X { int value_type; }; and pass that to the template). However without that function, the code could not be parsed (because the meaning of constructs changes depending on whether some identifier designates a type or a variable, e.g.T * p may be a multiplication or a pointer declaration). Therefore the rule is that everything which might be either type or variable and is not explicitly marked as type by prefixing it with typename is considered a variable.

like image 56
celtschk Avatar answered Sep 20 '22 04:09

celtschk


Use the typename keyword to indicate that it's really a type.

void push(typename T::value_type& item)

typename T::value_type pop()
like image 29
Mark Ransom Avatar answered Sep 20 '22 04:09

Mark Ransom


Here is a full implementation of the accepted answers above, in case it helps anyone.

#include <iostream>
#include <list>

template <typename T>
class C1 {
  private:
    T container;
    typedef typename T::value_type CT;
  public:
    void push(CT& item) {
        container.push_back(item);
    }

    CT pop (void) {
        CT item = container.front();
        container.pop_front();
        return item;
    }
};

int main() {
    int i = 1;
    C1<std::list<int> > c;
    c.push(i);
    std::cout << c.pop() << std::endl;
}
like image 38
Goblinhack Avatar answered Sep 20 '22 04:09

Goblinhack