C++ 如何使用常量引用作为模板参数?
我试图实现一种矩阵包装器,它将容器的容器作为模板参数 但我在尝试构造常量引用的矩阵包装器时出错。这段代码似乎使用了一个非引用、非指针、非常量参数,我想对这两种情况使用相同的代码。即使我会有另一个指针模板专门化 当我试图编译此代码时,会出现以下错误:C++ 如何使用常量引用作为模板参数?,c++,c++11,templates,vector,C++,C++11,Templates,Vector,我试图实现一种矩阵包装器,它将容器的容器作为模板参数 但我在尝试构造常量引用的矩阵包装器时出错。这段代码似乎使用了一个非引用、非指针、非常量参数,我想对这两种情况使用相同的代码。即使我会有另一个指针模板专门化 当我试图编译此代码时,会出现以下错误: >c:\users\emedeiros\source\repos\test\test\test.cpp(240): error C2079: 'matrix' uses undefined class 'matrix_wrapper<co
>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
>c:\users\emedeiros\source\repos\test\test\test.cpp(240):错误C2079:“matrix”使用未定义的类“matrix\u wrapper”
1> 与
1> [
1> _Ty=double
1> ]
1> c:\users\emedeiros\source\repos\test\test\test.cpp(240):错误C2440:“初始化”:无法从“const std::vector”转换为“int”
1> 与
1> [
1> _Ty=double
1> ]
1> c:\users\emedeiros\source\repos\test\test\test.cpp(240):注意:没有可以执行此转换的用户定义的转换运算符,或者无法调用该运算符
1.
下面您将找到类定义和一个函数,该函数将尝试创建一个matrix_包装器
#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);
}
#包括
模板
类矩阵包装器;
模板
类矩阵包装器,A2>>
{
公众:
typedef typename boost::call_traits::value_type value_type;
typedef typename boost::call_traits::param_type param_type;
typedef typename boost::call_traits::reference;
typedef Cont1矢量_type;
typedef typename boost::call_traits::reference vector_type_ref;
typedef typename boost::call_traits::const_参考向量_type_const_ref;
typedef T数据类型;
矩阵_包装器(参考数据):m_数据(数据){}
内联向量类型常数参考运算符[](大小i)常数
{
返回m_数据[i];
}
内联向量类型参考运算符[](大小i)
{
返回m_数据[i];
}
内联引用数据()
{
返回m_数据;
}
受保护的:
参考m_数据;
};
无效测试(常数标准::向量和数据)
{
矩阵_包装矩阵(数据);
}
int main()
{
std::vector v(10,std::vector(10,1));
试验(五);
}
我需要更改什么才能使用常量引用作为参数?我不会直接回答您的问题,但我敢猜您真正需要听到的是什么:) 首先,将引用作为模板类型通常不是一个好主意。如果您想制作一个包装器,在类中包装一个引用是有意义的,但最好将模板参数类型保持为值类型,而不是引用类型。话虽如此,如果您确实希望将引用类型作为参数,那么您可能需要使用
std::decay
然后,我看到这里有部分模板专门化。从你发布的代码来看,不清楚你是否真的需要它。我个人喜欢把事情简单化,所以我建议你不用它也行。在这种情况下,只需在一个且唯一的类型T
上对类进行参数化
请注意,不要声明函数inline
。编译器最适合你。默认情况下,在类的作用域中定义的方法是内联的。忘记inline
的意思是“请让代码更快”。这实际上意味着“此符号可能出现在多个翻译单元中,请为我选择一个定义”
最后,boost是一个很棒的库,但我不知道您在这里有多需要它。所有标准容器中都提供了所有必要的类型别名,只需询问即可
以下是根据我的评论简化的编译代码:
#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);
}
#包括
模板
类矩阵包装器
{
公众:
使用reference=const T&;
使用vector_type_ref=typename T::reference;
使用vector_type_const_ref=typename T::const_reference;
矩阵_包装器(参考数据):m_数据(数据){}
向量类型常数参考运算符[](大小i)常数
{
返回m_数据[i];
}
//顺便说一句,这不会为非常量对象编译,因为您存储了常量
//引用容器,但这是另一个故事
向量类型参考运算符[](大小i)
{
返回m_数据[i];
}
参考数据()
{
返回m_数据;
}
受保护的:
参考m_数据;
};
无效测试(常数标准::向量和数据)
{
矩阵_包装矩阵(数据);
}
int main()
{
std::vector v(10,std::vector(10,1));
试验(五);
}
请参见此处的实时演示:
我看到您在main()
中将v
声明为int
s的vector
,但在test()
中接受vector
的double
。我认为这是一个印刷错误,并修复了类型
我完全同意@NathanOliver关于1D/2D的观点,但这又是另一回事。FWIW你真的不想对矩阵使用2D向量吗。它们没有保证的缓存局部性,因此在计算量大的代码中,它们可能成为真正的性能瓶颈。不幸的是,由于一些限制,这里我不得不使用std::vector作为该矩阵的基础。这很好,但只使用一维。二维向量可以由两个维度相乘的一维向量替换。