9

So basic, but hard to search that in Google for me.

I am doing a C++ training course online and the topic is STL; in this case vector.

Is it possible to instantiate a vector without specifying the type?

#include <vector>
#include <iostream>

using namespace std;

int main()
{
    vector v1(10, 0);
    cout<<"Size: "<<v1.size()<<endl;
    for(unsigned i = 0; i < v1.size(); ++i)
    {
        cout<< v1[i]<<" ";
    }
    cout<<endl;
    return 0;
}

I think that is wrong, but I see that throughout the course and this confuses me.

When use vector<int> v1(10, 0) then it compiles, and that is how it should be I think.

In the course we are using NetBeans, but I don't think there is a config or parameter or anything that can make that happen, is there?

Ely
  • 10,860
  • 4
  • 43
  • 64
  • 8
    No it's not possible, you have to specify the type. – Borgleader Jul 17 '15 at 16:28
  • 3
    No, you can't deduce class template arguments from a constructor. There are some proposals for such a feature, but they're highly controversial. – Kerrek SB Jul 17 '15 at 16:29
  • 1
    You can have an alias that will make the above code compile.(e.g. typedef std::vector vector;) but I suspect it is not what you were asking. – alexm Jul 17 '15 at 16:31
  • You van full it with a boost::any I suppose, but that's hardly the same... – atlaste Jul 17 '15 at 16:32
  • In theory, you could define an alias by `using vector = std::vector;` and then use `vector` instead of `std::vector`. But it wouldn't work in your case as it would introduce an ambiguity with the `using namespace std;`. But you could say `using numbervector = std::vector;` or however you like to call it. – 5gon12eder Jul 17 '15 at 16:34
  • @dasblinkenlight As Kerrek said, deduce it from the ctor args, specifically the `val` argument to the fill ctor. `auto` does something similar, after all. – Peter - Reinstate Monica Jul 17 '15 at 16:37

6 Answers6

9

C++17 does support instantiation of vectors without type. Please see this article, https://en.cppreference.com/w/cpp/language/class_template_argument_deduction

for more information.

So, for instance writing this will work:

vector v {1, 2, 3};  // instead of vector<int>

if you compile with this "-std=c++17" flag.

MSC
  • 141
  • 2
  • 4
4

Templates in general

Ignoring the details of std::vector for the moment, it is possible to define a default type for a template parameter of a class template. For example:

template <class T = int>
class foo { 
    T *bar;
};

In such a case, you don't have to specify a type to instantiate that template. At the same time, you do have to include a template parameter list. The trick is that the list can be empty, so you could instantiate this template in any of the following ways:

foo<long> a; // instantiate over long. The `int` default is just ignored
foo<int>  b; // instantiate over int. Still doesn't use default
foo<>     c; // also instantiates over int

std::vector specifically

std::vector does use a default parameter for the type of the allocator, but does not provide a default for the type being stored, so the definition looks something like this:

template <class T, class allocator = std::allocator<T>>
class vector
// ...

So, if you don't specify otherwise, the allocator type for the vector will be an std::allocator instantiated over the same type as you're storing--but you do always have to specify a type you're storing, because no default is provided for that type.

Summary

It is definitely possible to specify defaults for all the parameters to a template, in which case it's possible to instantiate the template without (explicitly) specifying the type at the instantiation--but std::vector has one template parameter for which no default is provided, so to instantiate vector, you must specify a type for that parameter.

Community
  • 1
  • 1
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
3

No, std::vector is a template and cannot be instantiated without specifying the template parameters.

Alexander Balabin
  • 2,055
  • 11
  • 13
3

You must specify the type because it is not inferred from the parameters of the constructor. However, nobody forbids you to do this

std::vector<int> make_vector(std::vector<int>::size_type n, int val)
{
      return std::vector<int>(n, val);
}

// ...
auto v2 = make_vector(10, 0);

As why this is not possible, take a look at this question and related ones.

edmz
  • 8,220
  • 2
  • 26
  • 45
  • hmm interesting, given functions _can_ deduce template arguments you could extend this by templating on the value type. Something like: `template std::vector make_vector(size_type size, value_type val) { ... }` – PeterSW Jul 17 '15 at 16:56
  • @PeterSW `size_type` doesn't need (and shouldn't) be a template parameter. – edmz Jul 17 '15 at 17:41
3

It is possible (with a different setup):

#include <vector>
#include <iostream>

using std::cout;
using std::endl;
using vector = std::vector<int>;

int main()
{
    vector v1(10, 0);
    cout<<"Size: "<<v1.size()<<endl;
    for(unsigned i = 0; i < v1.size(); ++i)
    {
        cout<< v1[i]<<" ";
    }
    cout<<endl;
    return 0;
}

Note, use 'using' carefully.

0

Beside it being a syntax error, a vector without a type would be logically meaningless. You are asking for a list, but a list of nothing... What exactly were you expecting it to print out?

James Curran
  • 101,701
  • 37
  • 181
  • 258
  • 1
    It's a code sample from a course. I could not compile it because of said *error*. – Ely Jul 17 '15 at 16:56