Reputation: 45
I am trying to implement a kind of matrix wrapper that takes a container of a container as template parameter.
But I get an error when trying to construct a matrix_wrapper of a const reference. The code seems to work with a non reference, non pointer, not const parameter and I would like to use the same code for both cases. Even though I'll have another template specialization for pointers.
When I try to compile this code I get the following errors:
>c:\users\emedeiros\source\repos\test\test\test.cpp(240): error C2079: 'matrix' uses undefined class 'matrix_wrapper<const std::vector<std::vector<double,std::allocator<_Ty>>,std::allocator<std::vector<_Ty,std::allocator<_Ty>>>> &>'
1> with
1> [
1> _Ty=double
1> ]
1>c:\users\emedeiros\source\repos\test\test\test.cpp(240): error C2440: 'initializing': cannot convert from 'const std::vector<std::vector<double,std::allocator<_Ty>>,std::allocator<std::vector<_Ty,std::allocator<_Ty>>>>' to 'int'
1> with
1> [
1> _Ty=double
1> ]
1>c:\users\emedeiros\source\repos\test\test\test.cpp(240): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1
Below you'll find the class definition and a function that will try to create a matrix_wrapper.
#include <vector>
template <class T>
class matrix_wrapper;
template <typename T, class A1, class A2, template <typename, typename> class Cont1, template <typename, typename> class Cont2>
class matrix_wrapper < Cont2 < Cont1 < T, A1>, A2> >
{
public:
typedef typename boost::call_traits<Cont2<Cont1<T, A1>, A2>>::value_type value_type;
typedef typename boost::call_traits<value_type>::param_type param_type;
typedef typename boost::call_traits<value_type>::reference reference;
typedef Cont1<T, A1> vector_type;
typedef typename boost::call_traits<vector_type>::reference vector_type_ref;
typedef typename boost::call_traits<vector_type>::const_reference vector_type_const_ref;
typedef T data_type;
matrix_wrapper(reference data) : m_data(data) {}
inline vector_type_const_ref operator[](size_t i) const
{
return m_data[i];
}
inline vector_type_ref operator[](size_t i)
{
return m_data[i];
}
inline reference data()
{
return m_data;
}
protected:
reference m_data;
};
void test(const std::vector<std::vector<double>>& data)
{
matrix_wrapper<const std::vector<std::vector<double>>&> matrix(data);
}
int main()
{
std::vector<std::vector<int>> v(10, std::vector<int>(10, 1));
test(v);
}
What do I have to change so I can use a const reference as parameter?
Upvotes: 1
Views: 976
Reputation: 21749
I won't directly answer your question, but I dare to guess what you really need to hear :)
First, having references as types of templates is not usually a good idea. If you want to make a wrapper, it makes sense to have a reference on a wrapped inside your class, but it is still better to keep template parameter type to be a value type, not a reference type. Having said that, if you are really sure you want to have reference type as a parameter, you might want to play with std::decay
.
Then, I see you have partial template specialization here. From the code you posted it is not clear if you actually need it or not. I personally love to keep things simple, so I'd suggest you're good without it. In this case just parametrize your class on the one and only type T
.
As a side note, do not declare your functions inline
. Compiler knows best for you. And methods defined in scope of a class are inline
by default anyway. Forget that inline
means "please make this code faster". This actually means "this symbol might appear in several translation units, please pick a single definition for me".
Finally, boost is a great library, but I don't see how you need it here. All standard containers provide all the necessary type aliases in them, just ask.
Here is the compiling code simplified according to my comments:
#include <vector>
template <class T>
class matrix_wrapper
{
public:
using reference = const T&;
using vector_type_ref = typename T::reference;
using vector_type_const_ref = typename T::const_reference;
matrix_wrapper(reference data) : m_data(data) {}
vector_type_const_ref operator[](size_t i) const
{
return m_data[i];
}
// BTW this won't compile for non-const objects, since you store a const
// reference to the container, but that's a different story
vector_type_ref operator[](size_t i)
{
return m_data[i];
}
reference data()
{
return m_data;
}
protected:
reference m_data;
};
void test(const std::vector<std::vector<int>>& data)
{
matrix_wrapper<std::vector<std::vector<int>>> matrix(data);
}
int main()
{
std::vector<std::vector<int>> v(10, std::vector<int>(10, 1));
test(v);
}
See live demo here: https://wandbox.org/permlink/tmemloS6wCHZlhNY
I see that you declared v
in main()
as a vector
of int
s, but you accept a vector
of double
in test()
. I assumed this is a misprint and fixed the types.
I completely agree with @NathanOliver about 1D/2D thing, but that's again a different story.
Upvotes: 1