subclass does not deduce template argument in class with using std::vector<T>::vector

Hi,

I have this subclass of std::vector

1
2
3
4
5
6
7
8
9
10
11
12
13
14
template<typename T>
class Vec : public std::vector<T> 
{	
public:
    using std::vector<T>::vector; // use the constructors from vector
    T& operator[](int i) 						// range check
    {
        return std::vector<T>::at(i);
    }
    const T& operator[](int i) const 	// range check const objects
    {
        return std::vector<T>::at(i);
    }
};


Class Vec should inherit all vector constructors but it does not deduce templates!

See:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void useVec()
{
    list lst{ 2,7,12,35 };
    // vector constructors
    vector<int> vec(10, 5);        // create a 10 element vector with values 5
    vector vvec{ 1,3,5,7,9,11,13 };         // create a vector with these values
    vector vlist{ lst.begin(),lst.end() };  // create a vector with elements from list object lst
    vector vcopy{ vvec };                   // copy constructor

    Vec<int> v(10, 5);
    Vec vvec2{ 1,3,5,7,9,11,13 };         // error: does not deduce T being int
    Vec vvlist{ lst.begin(),lst.end() };  // error: does not deduce T begin int


    v[3] = 5;
    std::cout << v[3];
	
}


Why??
It seems like deduction guides were not inherited before C++23.

https://en.cppreference.com/w/cpp/container/vector/deduction_guides
https://stackoverflow.com/a/61311540
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2582r1.pdf

GCC 14 claims to implement P2582 but your code still doesn't compile: https://godbolt.org/z/f3K7d8he7

But if I comment out your operator[] then it compiles: https://godbolt.org/z/nPc5cbjKv

I don't know what that is about. It's a very new feature so maybe it's a compiler bug. According to cppreference.com, none of the other big compilers support this feature yet.

Last edited on
JUANDENT, it seems you're the very first one who noticed this in all these years:
https://cplusplus.com/forum/general/156923/#msg805416

As a workaround, you could simply explicitly call the base class constructor:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <type_traits>
#include <vector>


template <typename T, typename Allocator = std::allocator<T>>
class Vec : public std::vector<T> {	
    using std::vector<T>::vector;

public:
    Vec( std::initializer_list<T> init, Allocator const& alloc = Allocator() );

    T& operator[](int i)
    {
        return std::vector<T>::at(i);
    }
    const T& operator[](int i) const
    {
        return std::vector<T>::at(i);
    }
};


template <typename T, typename Allocator>
Vec<T, Allocator>::Vec( std::initializer_list<T> init, Allocator const& alloc )
    : std::vector<T, Allocator>(init, alloc)
{
}


void useVec()
{
    std::vector<int> lst { 2, 7, 12, 35 };

    std::vector<int> vec( 10, 5 );
    std::vector vvec { 1, 3, 5, 7, 9, 11, 13 };
    std::vector vlist { lst.begin(), lst.end() };
    std::vector vcopy { vvec };

    Vec<int> v( 10, 5 );
    Vec vvec2 { 1, 3, 5, 7, 9, 11, 13 };
    Vec vvlist { lst.begin(), lst.end() };

    v[3] = 5;
    std::cout << v[3];
}


int main()
{
    useVec();
}


And, yes, you could also provide code which is ready to be compiled, next time :-)

Have a nice day.
The class needs to be declared with 2 parameters like std::vector!
That fixes everything!!
Topic archived. No new replies allowed.