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

Jul 13, 2024 at 4:19pm
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??
Jul 13, 2024 at 6:46pm
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 Jul 13, 2024 at 7:00pm
Jul 13, 2024 at 7:35pm
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.
Jul 14, 2024 at 12:07am
The class needs to be declared with 2 parameters like std::vector!
That fixes everything!!
Topic archived. No new replies allowed.