- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
GCC 和 MSVC 在矩阵与模板相乘的方法上抛出一个编译错误,而 Clang 编译成功没有任何错误,我不明白为什么。有人可以提出什么问题吗?
我认为实例化 operator*(matrix, matrix)
存在问题。
注意:(错误:函数模板重定义,C2995:函数模板已经定义)[声明和定义在一个.hpp中,有header guards]
我在 gcc 7.2.0 及更高版本和 MSVC 19.14.26428.1 及更高版本上对此进行了测试。我也使用 C++17 标准。
有问题的方法:
template <std::size_t Rows_lhs, std::size_t Columns_lhs,
std::size_t Rows_rhs, std::size_t Columns_rhs>
friend constexpr matrix<value_type, Rows_lhs, Columns_rhs> operator*(
const matrix<value_type, Rows_lhs, Columns_lhs>& lhs,
const matrix<value_type, Rows_rhs, Columns_rhs>& rhs)
{
static_assert(Columns_lhs == Rows_rhs, "Incorrect matrix for product!");
matrix<value_type, Rows_lhs, Columns_rhs> result{};
container<value_type, Rows_rhs> thatColumn{};
for (size_type j = 0; j < Columns_rhs; ++j)
{
for (size_type k = 0; k < Rows_rhs; ++k)
{
thatColumn.at(k) = rhs(k, j);
}
for (size_type i = 0; i < Rows_lhs; ++i)
{
const auto thisRow = lhs(i);
value_type summand{};
for (size_type k = 0; k < Rows_rhs; ++k)
{
summand += thisRow.at(k) * thatColumn.at(k);
}
result(i, j) = summand;
}
}
return result;
}
完整代码:
#include <iostream>
#include <string>
#include <cmath>
#include <iterator>
#include <algorithm>
#include <array>
#include <initializer_list>
namespace vv
{
template <class Type = double, std::size_t Rows = 1, std::size_t Columns = 1>
class matrix
{
public:
using value_type = Type;
using size_type = std::size_t;
template <class Type = value_type, std::size_t N = Rows>
using container = std::array<Type, N>;
using row_container = container<value_type, Columns>;
using row_container_reference = container<value_type, Columns>&;
using const_row_container_reference = const container<value_type, Columns>&;
using reference = value_type&;
using const_reference = const value_type&;
using std_matrix = matrix<value_type, Rows, Columns>;
static constexpr value_type EPS = static_cast<value_type>(1e-10);
static_assert(std::is_arithmetic_v<value_type>, "Matrix elements type has to be arithmetic!");
static_assert(Rows > 0 && Columns > 0, "Incorrect size parameters!");
constexpr matrix() = default;
constexpr matrix(const std::initializer_list<value_type> list)
: _data()
{
size_type row_counter = 0;
size_type col_counter = 0;
for (const auto elem : list)
{
_data.at(row_counter).at(col_counter) = elem;
++col_counter;
if (row_counter == Rows && col_counter == Columns)
{
break;
}
if (col_counter == Columns)
{
col_counter = 0;
++row_counter;
}
}
}
std::string get_dimension() const noexcept
{
return std::to_string(Rows) + std::string("x")
+ std::to_string(Columns);
}
constexpr const_reference operator()(const size_type i, const size_type j) const
{
return _data.at(i).at(j);
}
constexpr reference operator()(const size_type i, const size_type j)
{
return _data.at(i).at(j);
}
constexpr const_row_container_reference& operator()(const size_type i) const
{
return _data.at(i);
}
constexpr row_container_reference& operator()(const size_type i)
{
return _data.at(i);
}
constexpr std_matrix& operator*=(const value_type num) noexcept
{
for (auto& row : _data)
{
for (auto& elem : row)
{
elem *= num;
}
}
return *this;
}
friend constexpr std_matrix operator*(const std_matrix& mat, const value_type num) noexcept
{
std_matrix temp(mat);
return (temp *= num);
}
friend constexpr std_matrix operator*(const value_type num, const std_matrix& mat) noexcept
{
return (mat * num);
}
friend std::ostream& operator<<(std::ostream& os, const std_matrix& mat)
{
os << "[" << mat.get_dimension() << "]\n";
for (const auto& row : mat._data)
{
std::copy(std::begin(row), std::end(row),
std::ostream_iterator<value_type>(os, " "));
os << '\n';
}
return os;
}
// PROBLEMS HERE BEGIN
template <std::size_t Rows_lhs, std::size_t Columns_lhs,
std::size_t Rows_rhs, std::size_t Columns_rhs>
friend constexpr matrix<value_type, Rows_lhs, Columns_rhs> operator*(
const matrix<value_type, Rows_lhs, Columns_lhs>& lhs,
const matrix<value_type, Rows_rhs, Columns_rhs>& rhs)
{
static_assert(Columns_lhs == Rows_rhs, "Incorrect matrix for product!");
matrix<value_type, Rows_lhs, Columns_rhs> result{};
container<value_type, Rows_rhs> thatColumn{};
for (size_type j = 0; j < Columns_rhs; ++j)
{
for (size_type k = 0; k < Rows_rhs; ++k)
{
thatColumn.at(k) = rhs(k, j);
}
for (size_type i = 0; i < Rows_lhs; ++i)
{
const auto thisRow = lhs(i);
value_type summand{};
for (size_type k = 0; k < Rows_rhs; ++k)
{
summand += thisRow.at(k) * thatColumn.at(k);
}
result(i, j) = summand;
}
}
return result;
}
// END
private:
container<container<value_type, Columns>, Rows> _data;
};
} // namespace vv
int main()
{
constexpr vv::matrix<double, 2, 1> a{ 1.0, 2.0 };
constexpr vv::matrix<double, 1, 2> b{ 4.0, 3.0 };
constexpr auto c = a * b; // This code occurs error.
std::cout << c;
return 0;
}
最佳答案
问题是 operator*()
在模板内部定义matrix
类。
因此,当您定义 matrix
对象,说 matrix<double, 1, 2>
, 这个函数被定义了;当您定义另一个具有相同类型和不同维度的对象时,比如说 matrix<double, 2, 1>
, 重新定义了完全相同的模板函数。
在我看来,没有什么需要该函数是 friend
的 matrix
所以——建议——在类内部删除,在类外部重写,如下
template <class Type, std::size_t N>
using container = std::array<Type, N>;
using size_type = std::size_t;
template <typename value_type, std::size_t Rows_lhs, std::size_t Columns_lhs,
std::size_t Rows_rhs, std::size_t Columns_rhs>
constexpr matrix<value_type, Rows_lhs, Columns_rhs> operator*(
const matrix<value_type, Rows_lhs, Columns_lhs>& lhs,
const matrix<value_type, Rows_rhs, Columns_rhs>& rhs)
{
static_assert(Columns_lhs == Rows_rhs, "Incorrect matrix for product!");
matrix<value_type, Rows_lhs, Columns_rhs> result{};
container<value_type, Rows_rhs> thatColumn{};
for (size_type j = 0; j < Columns_rhs; ++j)
{
for (size_type k = 0; k < Rows_rhs; ++k)
{
thatColumn.at(k) = rhs(k, j);
}
for (size_type i = 0; i < Rows_lhs; ++i)
{
const auto thisRow = lhs(i);
value_type summand{};
for (size_type k = 0; k < Rows_rhs; ++k)
{
summand += thisRow.at(k) * thatColumn.at(k);
}
result(i, j) = summand;
}
}
return result;
}
如果你真的想要,你可以维护它friend
但只在类中声明它 matrix
template <typename value_type, std::size_t Rows_lhs,
std::size_t Columns_lhs, std::size_t Rows_rhs,
std::size_t Columns_rhs>
friend constexpr matrix<value_type, Rows_lhs, Columns_rhs> operator*(
const matrix<value_type, Rows_lhs, Columns_lhs>& lhs,
const matrix<value_type, Rows_rhs, Columns_rhs>& rhs);
奖金(题外话)建议:不需要定义四个矩阵维度并用static_assert()
强加。第二个 ( Columns_lhs
) 和第三个 ( Rows_rsh
) 是相等的。
您可以将它们统一在一个模板参数中( midDim
,在以下示例中)
template <typename value_type, std::size_t Rows_lhs, std::size_t midDim,
std::size_t Columns_rhs>
constexpr matrix<value_type, Rows_lhs, Columns_rhs> operator*(
const matrix<value_type, Rows_lhs, midDim>& lhs,
const matrix<value_type, midDim, Columns_rhs>& rhs)
{
matrix<value_type, Rows_lhs, Columns_rhs> result{};
container<value_type, midDim> thatColumn{};
for (size_type j = 0; j < Columns_rhs; ++j)
{
for (size_type k = 0; k < midDim; ++k)
{
thatColumn.at(k) = rhs(k, j);
}
for (size_type i = 0; i < Rows_lhs; ++i)
{
const auto thisRow = lhs(i);
value_type summand{};
for (size_type k = 0; k < midDim; ++k)
{
summand += thisRow.at(k) * thatColumn.at(k);
}
result(i, j) = summand;
}
}
return result;
}
关于c++ - 错误 : redefinition of function template (or C2995),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50193468/
我正在尝试制作一个压缩和解压缩文件的程序。我想为操作类型创建这样的枚举:typedef enum { COMPRESS, DECOMPRESS } operation;。问题是,我收到 4 个错误:
此代码会导致编译错误“错误:使用不同类型重新定义'p'”: void fun() { printf("fun"); } void (*p)(); p = &fun; 但是如果修改 void (
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题吗? 通过 editing this post 添加细节并澄清问题. 关闭 8 年前。 Improve t
这个问题在这里已经有了答案: Avoiding "redefinition of typedef" warnings when defining structs (2 个答案) 关闭 5 年前。 我
对于以下使用 Visual C++ 2010 的代码,我有一个奇怪的编译警告: #include class test { public: template
我有两个库(第三方),在每个库中,它们都定义了两个同名的类(在头文件中)。 // Lib A, HeaderA.h struct mycompare { //Some code }; // Lib B
关闭。这个问题是not reproducible or was caused by typos .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 5年前关闭。 Imp
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我正在处理类里面的一个问题。它是关于创建一个“addressType”类,并使用它与已经写出的主函数进行交互。该程序无法运行,我得到的主要错误是“addressType.cpp:6:7: error:
我的 C++ 代码有一些问题。我现在正在尝试拆分一个头文件,该文件具有一些 char 指针的定义和声明(以前是字符串,但我遇到了一些 CRT 问题,因此将它们更改为 char 指针)。由于我已将它们更
我已经很久不用C++了,对它不是很友好。我正在恢复我的一个旧项目并尝试编译它,但我在启动 Makefile 时收到以下错误输出: g++ -W -ggdb3 -Wall -ansi -pedantic
我正在尝试构建一个链表,但我一开始就卡住了——我是一个完全的初学者。如何定义结构? 这是我收到的错误消息: 8 8 C:\Users\user\Desktop\list_funcs.c [错误] 's
这是我的代码: // in main.cpp #include "iostream" #include "circle.cpp" #include "rectangle.cpp" #include "
我有一个 iOS xcode 项目,当我选择 Generic iOS Device 作为我的目的地时,它构建得很好。但是,当我选择任何模拟器选项时,我的构建失败并出现许多 Redefinition o
我正在尝试将用户空间库链接到 Windows 内核驱动程序。它引用了 __iob_func,它是“libcmt.lib”(用户空间库)的一部分。我无法在 winddk 中访问此功能。因此,我计划为 _
在下面的代码中: typedef struct { union U { int a; char b; }U1;
我正在做一个大项目,我收到这个警告: ...\include\stddef.h" 38/9] macro "NULL" redefined ...\ncs_types.h" 125/13] previ
我在这里有这段代码,并且出现了GCC错误:在此代码的开头重新定义了union semun。 union semun { int val; /* Value fo
我是 javascript/typescript 开发人员,但对 Arduino/c++ 很陌生 我有一个类(见下面的 h 和 cpp)并且有这个编译器错误: DotMatrix.cpp:13:1:
我遇到了奇怪的错误,其中大多数涉及第 9-12 行(函数声明),但我找不到问题。请帮助我:) 谢谢 代码: #include #include #include #include #defin
我是一名优秀的程序员,十分优秀!