已經有很多關于這個主題的帖子,但是沒有一個提議的解決方案幫助我編譯和/或鏈接我的代碼。
對此的一般建議解決方案是前向宣告類,前向宣告運算子/函式,將其宣告為友元,然后實作它。
我嘗試編譯的代碼是:
#include "matrix.hpp"
int main()
{
using namespace MLL;
Matrix<int, 4, 4> a({1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16});
a a;
return 0;
}
變體 1
#include <algorithm>
#include <array>
#include <type_traits>
#include <vector>
namespace MLL{
template<typename data_t, std::size_t n_rows, std::size_t n_cols, std::size_t MAX = 256>
class Matrix;
template<typename data_t, typename T, std::size_t n_rows, std::size_t n_cols, std::size_t MAX, std::size_t other_MAX>
Matrix<decltype(std::declval<data_t>() std::declval<T>()), n_rows, n_cols, std::min(MAX, other_MAX)>
operator (Matrix<data_t, n_rows, n_cols, MAX> const& lhs, Matrix<T, n_rows, n_cols, other_MAX> const& rhs);
template<typename data_t, std::size_t n_rows, std::size_t n_cols, std::size_t MAX>
class Matrix{
static constexpr bool IS_STATIC = n_rows * n_cols <= MAX;
using container_t = typename std::conditional<IS_STATIC, std::array<data_t, n_rows * n_cols>, std::vector<data_t>>::type;
container_t m_data_list;
public:
Matrix(){
if constexpr( !IS_STATIC ){
m_data_list.resize(n_rows * n_cols);
}
}
explicit Matrix(data_t default_value){
if constexpr( IS_STATIC ){
m_data_list.fill(default_value);
}else{
m_data_list.resize(n_rows * n_cols, default_value);
}
}
explicit Matrix(std::initializer_list<data_t>&& value_list){
std::copy(value_list.begin(), value_list.end(), m_data_list.begin());
}
Matrix(Matrix const& other)
: m_data_list(other.m_data_list){
}
Matrix(Matrix&& other) noexcept
: m_data_list(std::move(other.m_data_list)){
}
Matrix& operator=(Matrix const& other){
m_data_list = other.m_data_list;
return *this;
}
Matrix& operator=(Matrix&& other) noexcept{
m_data_list = std::move(other.m_data_list);
return *this;
}
template<typename T, std::size_t other_MAX>
friend Matrix<decltype(std::declval<data_t>() std::declval<T>()), n_rows, n_cols, std::min(MAX, other_MAX)>
operator (Matrix<data_t, n_rows, n_cols, MAX> const& lhs, Matrix<T, n_rows, n_cols, other_MAX> const& rhs);
};
template<typename data_t, typename T, std::size_t n_rows, std::size_t n_cols, std::size_t MAX, std::size_t other_MAX>
Matrix<decltype(std::declval<data_t>() std::declval<T>()), n_rows, n_cols, std::min(MAX, other_MAX)>
operator (Matrix<data_t, n_rows, n_cols, MAX> const& lhs, Matrix<T, n_rows, n_cols, other_MAX> const& rhs){
const std::size_t n = n_rows * n_cols;
for( std::size_t i = 0; i < n; i ){
lhs.m_data_list[i] = rhs.m_data_list[i];
}
return lhs;
}
}
此處聯結器抱怨該功能未實作。
undefined reference to `MLL::Matrix<decltype (((std::declval<int>)()) ((declval<int>)())), 4ull, 4ull, (std::min<unsigned long long>)(256ull, 256ull)> MLL::operator <int, 256ull>(MLL::Matrix<int, 4ull, 4ull, 256ull> const&, MLL::Matrix<int, 4ull, 4ull, 256ull> const&)'
變體 2
#include <algorithm>
#include <array>
#include <type_traits>
#include <vector>
namespace MLL{
template<typename data_t, std::size_t n_rows, std::size_t n_cols, std::size_t MAX = 256>
class Matrix;
template<typename data_t, typename T, std::size_t n_rows, std::size_t n_cols, std::size_t MAX, std::size_t other_MAX>
Matrix<decltype(std::declval<data_t>() std::declval<T>()), n_rows, n_cols, std::min(MAX, other_MAX)>
operator (Matrix<data_t, n_rows, n_cols, MAX> const& lhs, Matrix<T, n_rows, n_cols, other_MAX> const& rhs);
template<typename data_t, std::size_t n_rows, std::size_t n_cols, std::size_t MAX>
class Matrix{
static constexpr bool IS_STATIC = n_rows * n_cols <= MAX;
using container_t = typename std::conditional<IS_STATIC, std::array<data_t, n_rows * n_cols>, std::vector<data_t>>::type;
container_t m_data_list;
public:
Matrix(){
if constexpr( !IS_STATIC ){
m_data_list.resize(n_rows * n_cols);
}
}
explicit Matrix(data_t default_value){
if constexpr( IS_STATIC ){
m_data_list.fill(default_value);
}else{
m_data_list.resize(n_rows * n_cols, default_value);
}
}
explicit Matrix(std::initializer_list<data_t>&& value_list){
std::copy(value_list.begin(), value_list.end(), m_data_list.begin());
}
Matrix(Matrix const& other)
: m_data_list(other.m_data_list){
}
Matrix(Matrix&& other) noexcept
: m_data_list(std::move(other.m_data_list)){
}
Matrix& operator=(Matrix const& other){
m_data_list = other.m_data_list;
return *this;
}
Matrix& operator=(Matrix&& other) noexcept{
m_data_list = std::move(other.m_data_list);
return *this;
}
template<typename T, typename U, std::size_t m_rows, std::size_t m_cols, std::size_t this_MAX, std::size_t other_MAX>
friend Matrix<decltype(std::declval<T>() std::declval<U>()), m_rows, m_cols, std::min(this_MAX, other_MAX)>
operator (Matrix<T, m_rows, m_cols, this_MAX> const& lhs, Matrix<T, m_rows, m_cols, other_MAX> const& rhs);
};
template<typename data_t, typename T, std::size_t n_rows, std::size_t n_cols, std::size_t MAX, std::size_t other_MAX>
Matrix<decltype(std::declval<data_t>() std::declval<T>()), n_rows, n_cols, std::min(MAX, other_MAX)>
operator (Matrix<data_t, n_rows, n_cols, MAX> const& lhs, Matrix<T, n_rows, n_cols, other_MAX> const& rhs){
const std::size_t n = n_rows * n_cols;
for( std::size_t i = 0; i < n; i ){
lhs.m_data_list[i] = rhs.m_data_list[i];
}
return lhs;
}
}
錯誤 2
C:/Users/CLionProjects/MLL/include/matrix.hpp:68:17: error: 'MLL::Matrix<int, 4, 4>::container_t MLL::Matrix<int, 4, 4>::m_data_list' is private within this context
68 | lhs.m_data_list[i] = rhs.m_data_list[i];
| ~~~~^~~~~~~~~~~
C:/Users/CLionProjects/MLL/include/matrix.hpp:19:21: note: declared private here
19 | container_t m_data_list;
| ^~~~~~~~~~~
C:/Users/CLionProjects/MLL/include/matrix.hpp:68:39: error: 'MLL::Matrix<int, 4, 4>::container_t MLL::Matrix<int, 4, 4>::m_data_list' is private within this context
68 | lhs.m_data_list[i] = rhs.m_data_list[i];
| ~~~~^~~~~~~~~~~
C:/Users/CLionProjects/MLL/include/matrix.hpp:19:21: note: declared private here
19 | container_t m_data_list;
| ^~~~~~~~~~~h
C:/Users/CLionProjects/MLL/include/matrix.hpp:68:32: error: assignment of read-only location 'lhs.MLL::Matrix<int, 4, 4>::m_data_list.std::array<int, 16>::operator[](i)'
68 | lhs.m_data_list[i] = rhs.m_data_list[i];
| ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~
ninja: build stopped: subcommand failed.
問題
我不想在朋友宣告中定義它。
您能否解釋一下我在這兩種情況下做錯了什么,以及如何解決?
uj5u.com熱心網友回復:
第一個片段的問題是函式模板的朋友宣告operator 只有兩個引數,而實作operator 的模板引數有 6 個。也就是說,friend 宣告是針對與您實作的函式模板不同的函式模板。
另外請注意,您實際上并不需要Matrix模板和多載的前向宣告operator 。
在下面修改過的程式中,我洗掉了那些前向宣告(但如果你愿意,你可以擁有它們)并且我使用注釋突出顯示了我所做的更改。如果您確實決定使用前向宣告,請確保僅256在前向宣告中而不在定義中提供默認引數。
此外,為了更好的可讀性,我在多載的每個模板引數之后添加了后綴 ,以便可以輕松地將其與封閉類模板的模板引數分開。OPoperator
此外,作為lhsconst 左值參考,我們不能lhs.m_data_list[i] = rhs.m_data_list[i]使用該參考進行賦值。因此,在下面的代碼中,我已經注釋掉了該陳述句,如我的注釋所示。
作業演示
namespace MLL{
// template<typename data_t, std::size_t n_rows, std::size_t n_cols, std::size_t MAX=256>
// class Matrix; //this forward declaration not needed but you can have this if you want and if you do then make sure that you only provide the default arg 256 in declaration and not in definition
//--------------------------------------------------------------------------------vvvvvvv---->added this default arg here instead of in forward declaration
template<typename data_t, std::size_t n_rows, std::size_t n_cols, std::size_t MAX=256>
class Matrix{
static constexpr bool IS_STATIC = n_rows * n_cols <= MAX;
using container_t = typename std::conditional<IS_STATIC, std::array<data_t, n_rows * n_cols>, std::vector<data_t>>::type;
container_t m_data_list;
public:
Matrix(){
if constexpr( !IS_STATIC ){
m_data_list.resize(n_rows * n_cols);
}
}
explicit Matrix(data_t default_value){
if constexpr( IS_STATIC ){
m_data_list.fill(default_value);
}else{
m_data_list.resize(n_rows * n_cols, default_value);
}
}
explicit Matrix(std::initializer_list<data_t>&& value_list){
std::copy(value_list.begin(), value_list.end(), m_data_list.begin());
}
Matrix(Matrix const& other)
: m_data_list(other.m_data_list){
}
Matrix(Matrix&& other) noexcept
: m_data_list(std::move(other.m_data_list)){
}
Matrix& operator=(Matrix const& other){
m_data_list = other.m_data_list;
return *this;
}
Matrix& operator=(Matrix&& other) noexcept{
m_data_list = std::move(other.m_data_list);
return *this;
}
//renamed all the arguments by prefexing them with OP for better readibility
template<typename data_tOP, typename TOP, std::size_t n_rowst, std::size_t n_colsOP, std::size_t MAXOP, std::size_t other_MAXOP>
friend Matrix<decltype(std::declval<data_tOP>() std::declval<TOP>()), n_rowst, n_colsOP, std::min(MAXOP, other_MAXOP)>
operator (Matrix<data_tOP, n_rowst, n_colsOP, MAXOP> const& lhs, Matrix<TOP, n_rowst, n_colsOP, other_MAXOP> const& rhs);
};
template<typename data_tOP, typename TOP, std::size_t n_rowst, std::size_t n_colsOP, std::size_t MAXOP, std::size_t other_MAXOP>
Matrix<decltype(std::declval<data_tOP>() std::declval<TOP>()), n_rowst, n_colsOP, std::min(MAXOP, other_MAXOP)>
operator (Matrix<data_tOP, n_rowst, n_colsOP, MAXOP> const& lhs, Matrix<TOP, n_rowst, n_colsOP, other_MAXOP> const& rhs){
const std::size_t n = n_rowst * n_colsOP;
for( std::size_t i = 0; i < n; i ){
// lhs.m_data_list[i] = rhs.m_data_list[i]; //can't assing using const lvalue reference
}
return lhs;
}
}
作業演示
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/524146.html
標籤:C 模板运算符重载
上一篇:在vue模板上重用函式的相同值
下一篇:如何迭代模板類?
