我有一个当前正在测试的自定义链接列表容器。我的测试之一是首先构建容器以接受 uint8_t 类型,然后尝试插入 float 类型并触发异常。问题是在我的附加函数中,附加了浮点数而没有触发我的异常块。当我打印数据时,存储浮点数的节点的实际内容不会显示,但链表的大小在追加后发生变化,所以看起来确实是数据被追加了。
如何检查类型以强制在这种特殊情况下抛出运行时错误?
这是我的附加函数代码和失败的测试。
...
template <typename T>
void libdsa::libstructures::LinkedList<T>::append(T datum)
{
// Triggers even during a valid insertion.
// if (typeid(datum) != typeid(this))
// {
// throw std::runtime_error("Invalid type being inserted.");
// }
// Fill the head node if it's empty. Otherwise append a new node.
if (_head == nullptr)
{
try
{
_head = new libdsa::libstructures::Node<T>(datum);
_head->_next = _head;
_head->_prev = _head;
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
}
}
else
{
try
{
libdsa::libstructures::Node<T> *current = _head;
// Create the new node
libdsa::libstructures::Node<T> *newNode = new libdsa::libstructures::Node<T>(datum);
// Go to the end of the list
while (current->_next != _head)
{
current = current->_next;
}
// Append the new node and set the directional pointers.
current->_next = newNode;
newNode->_prev = current;
newNode->_next = _head;
}
catch(const std::exception& e)
{
std::cerr << e.what() << '\n';
}
}
++_size;
}
...
TEST(LinkedList, testInvalidAppend)
{
std::vector<uint8_t> data = {'C', 'O', 'D', 'E'};
auto list = setup(data);
float temp = 23.22;
list.append(temp);
list.print();
ASSERT_EQ(data.size(), list.getSize());
}
libdsa::libstructures::LinkedList<uint8_t> setup(std::vector<uint8_t> &data)
{
libdsa::libstructures::LinkedList<uint8_t> list;
for (size_t i = 0; i < data.size(); ++i)
{
list.append(data[i]);
}
return list;
}
我希望在执行此无效操作时抛出异常(或运行时错误),但无论有或没有我的条件语句,目前都不会触发异常。
最初,我尝试使用 try-catch 块,认为编译器会为我捕获它并打印出异常。然而,它并没有触发它并分配数据块。我尝试的另一个选项是在运行时获取正在插入的数据和容器类型的 typeid,但这在成功的情况下导致插入失败(其中数据和容器的类型实际上是相同的) .
问题是
float
已经在运行时转换为 uint8_t
,因此如果没有编译时解决方案,您无法检查它。
如果您使用的是 C++17 或更高版本,则可以利用
constexpr if
:
template <typename T>
void libdsa::libstructures::LinkedList<T>::append(T datum)
{
if constexpr (!std::is_same_v<T, uint8_t>)
{
std::cout << "This is an invalid type " << datum << "\n";
return; // or throw an exception
}
//...
}
如果类型不是
uint8_t
,则 if
块是 true
并且将执行代码。
这是一个实例
如果您想在发送错误类型时停止编译并且根本不生成可执行文件,您可以使用
static_assert
(适用于 C++11):
#include <cstdint>
//...
template <typename T>
void libdsa::libstructures::LinkedList<T>::append(T datum)
{
// This will stop the compilation if the wrong type is sent
static_assert(std::is_same_v<T, uint8_t>, "It is not a uint8_t");
//...
}
这是一个实例