如何根据在 C++ 中使用模板调用的类型使我的函数 return 产生不同的结果
How do I make my function return different results depending on type it's been called using templates in C++
我一直在寻找我的问题的答案,但找不到任何有效的答案。
基本上,我有一个二叉搜索树和一个搜索函数:
T BinarySearchTree::Search(Node *tree, int key) const {
if (tree == nullptr) // if root is null, key is not in tree
return false;
if (key == tree->key) // key is found
return true;
else if (key < tree->key) // recursively look at left subtree if key < tree->key
return Search<T>(tree->left, key);
else // recursively look at right subtree if key > tree->key
return Search<T>(tree->right, key);
}
我想 return 根据调用的类型来做不同的事情。例如。如果我将函数调用为 Search<bool>()
,我希望它为 return true 或 false,但如果我调用 Search<Node*>
,我希望它为 return 一个指针。它应该看起来像这样:
T BinarySearchTree::Search(Node *tree, int key) const {
if (key == tree->key){ // key is found
if(T = bool)
return true;
else if(T = Node*)
return tree;
else if (T = int)
return tree->key;
}
我什至不确定模板是否适合此处,但如有任何实施提示,我们将不胜感激。
如评论中所述,从 API 可用性的角度来看,基于 return 类型的重载通常不是一个好主意(并且因为 C++ 不直接支持它,无论如何都需要一些技巧)。
相反,使用两个明确说明其作用的不同函数名称:
Node* BinarySearchTree::Search(Node* tree, int key) const {
// implement tree search
}
Node const* BinarySearchTree::Search(Node const* tree, int key) const {
return const_cast<Node const*>(Search(const_cast<Node*>(tree), key));
}
bool BinarySearchTree::Contains(Node const* tree, int key) const {
return Search(tree, key) != nullptr;
}
此外,这些函数的 public API 应该没有 tree
参数,因为它只在内部需要。
您要求的 可以 在 C++17 及更高版本中使用 if constexpr
完成,例如:
#include <type_traits>
template<typename T>
T BinarySearchTree::Search(Node *tree, int key) const {
static_assert(
std::is_same_v<T, bool> ||
std::is_same_v<T, Node*> ||
std::is_same_v<T, int>,
"Invalid type specified");
if (tree == nullptr) {
if constexpr (std::is_same_v<T, bool>)
return false;
}
else if constexpr (std::is_same_v<T, Node*>) {
return nullptr;
}
else {
return 0; // or throw an exception
}
}
else if (key == tree->key) {
if constexpr (std::is_same_v<T, bool>)
return true;
}
else if constexpr (std::is_same_v<T, Node*>) {
return tree;
}
else {
return tree->key;
}
}
else if (key < tree->key)
return Search<T>(tree->left, key);
else
return Search<T>(tree->right, key);
}
在C++17之前,使用SFINAE可以得到类似的结果,例如:
#include <type_traits>
Node* BinarySearchTree::InternalSearch(Node *tree, int key) const {
if (tree == nullptr) {
return nullptr;
}
else if (key == tree->key) {
return tree;
}
else if (key < tree->key)
return Search<T>(tree->left, key);
else
return Search<T>(tree->right, key);
}
template<typename T>
typename std::enable_if<std::is_same<T, bool>::value, T>::type
BinarySearchTree::Search(Node *tree, int key) const {
return InternalSearch(tree, key) != nullptr;
}
template<typename T>
typename std::enable_if<std::is_same<T, Node*>::value, T>::type
BinarySearchTree::Search(Node *tree, int key) const {
return InternalSearch(tree, key);
}
template<typename T>
typename std::enable_if<std::is_same<T, int>::value, T>::type
BinarySearchTree::Search(Node *tree, int key) const {
tree = InternalSearch(tree, key);
return tree != nullptr ? tree->key : 0 /* or throw an exception */;
}
或者,使用模板专业化,例如:
Node* BinarySearchTree::InternalSearch(Node *tree, int key) const {
if (tree == nullptr) {
return nullptr;
}
else if (key == tree->key) {
return tree;
}
else if (key < tree->key)
return Search<T>(tree->left, key);
else
return Search<T>(tree->right, key);
}
template<typename T>
T BinarySearchTree::Search(Node *tree, int key) const {
// throw a suitable exception
}
template<>
bool BinarySearchTree::Search<bool>(Node *tree, int key) const {
return InternalSearch(tree, key) != nullptr;
}
template<>
Node* BinarySearchTree::Search<Node*>(Node *tree, int key) const {
return InternalSearch(tree, key);
}
template<>
int BinarySearchTree::Search<int>(Node *tree, int key) const {
tree = InternalSearch(tree, key);
return tree != nullptr ? tree->key : 0 /* or throw an exception */;
}
我一直在寻找我的问题的答案,但找不到任何有效的答案。
基本上,我有一个二叉搜索树和一个搜索函数:
T BinarySearchTree::Search(Node *tree, int key) const {
if (tree == nullptr) // if root is null, key is not in tree
return false;
if (key == tree->key) // key is found
return true;
else if (key < tree->key) // recursively look at left subtree if key < tree->key
return Search<T>(tree->left, key);
else // recursively look at right subtree if key > tree->key
return Search<T>(tree->right, key);
}
我想 return 根据调用的类型来做不同的事情。例如。如果我将函数调用为 Search<bool>()
,我希望它为 return true 或 false,但如果我调用 Search<Node*>
,我希望它为 return 一个指针。它应该看起来像这样:
T BinarySearchTree::Search(Node *tree, int key) const {
if (key == tree->key){ // key is found
if(T = bool)
return true;
else if(T = Node*)
return tree;
else if (T = int)
return tree->key;
}
我什至不确定模板是否适合此处,但如有任何实施提示,我们将不胜感激。
如评论中所述,从 API 可用性的角度来看,基于 return 类型的重载通常不是一个好主意(并且因为 C++ 不直接支持它,无论如何都需要一些技巧)。
相反,使用两个明确说明其作用的不同函数名称:
Node* BinarySearchTree::Search(Node* tree, int key) const {
// implement tree search
}
Node const* BinarySearchTree::Search(Node const* tree, int key) const {
return const_cast<Node const*>(Search(const_cast<Node*>(tree), key));
}
bool BinarySearchTree::Contains(Node const* tree, int key) const {
return Search(tree, key) != nullptr;
}
此外,这些函数的 public API 应该没有 tree
参数,因为它只在内部需要。
您要求的 可以 在 C++17 及更高版本中使用 if constexpr
完成,例如:
#include <type_traits>
template<typename T>
T BinarySearchTree::Search(Node *tree, int key) const {
static_assert(
std::is_same_v<T, bool> ||
std::is_same_v<T, Node*> ||
std::is_same_v<T, int>,
"Invalid type specified");
if (tree == nullptr) {
if constexpr (std::is_same_v<T, bool>)
return false;
}
else if constexpr (std::is_same_v<T, Node*>) {
return nullptr;
}
else {
return 0; // or throw an exception
}
}
else if (key == tree->key) {
if constexpr (std::is_same_v<T, bool>)
return true;
}
else if constexpr (std::is_same_v<T, Node*>) {
return tree;
}
else {
return tree->key;
}
}
else if (key < tree->key)
return Search<T>(tree->left, key);
else
return Search<T>(tree->right, key);
}
在C++17之前,使用SFINAE可以得到类似的结果,例如:
#include <type_traits>
Node* BinarySearchTree::InternalSearch(Node *tree, int key) const {
if (tree == nullptr) {
return nullptr;
}
else if (key == tree->key) {
return tree;
}
else if (key < tree->key)
return Search<T>(tree->left, key);
else
return Search<T>(tree->right, key);
}
template<typename T>
typename std::enable_if<std::is_same<T, bool>::value, T>::type
BinarySearchTree::Search(Node *tree, int key) const {
return InternalSearch(tree, key) != nullptr;
}
template<typename T>
typename std::enable_if<std::is_same<T, Node*>::value, T>::type
BinarySearchTree::Search(Node *tree, int key) const {
return InternalSearch(tree, key);
}
template<typename T>
typename std::enable_if<std::is_same<T, int>::value, T>::type
BinarySearchTree::Search(Node *tree, int key) const {
tree = InternalSearch(tree, key);
return tree != nullptr ? tree->key : 0 /* or throw an exception */;
}
或者,使用模板专业化,例如:
Node* BinarySearchTree::InternalSearch(Node *tree, int key) const {
if (tree == nullptr) {
return nullptr;
}
else if (key == tree->key) {
return tree;
}
else if (key < tree->key)
return Search<T>(tree->left, key);
else
return Search<T>(tree->right, key);
}
template<typename T>
T BinarySearchTree::Search(Node *tree, int key) const {
// throw a suitable exception
}
template<>
bool BinarySearchTree::Search<bool>(Node *tree, int key) const {
return InternalSearch(tree, key) != nullptr;
}
template<>
Node* BinarySearchTree::Search<Node*>(Node *tree, int key) const {
return InternalSearch(tree, key);
}
template<>
int BinarySearchTree::Search<int>(Node *tree, int key) const {
tree = InternalSearch(tree, key);
return tree != nullptr ? tree->key : 0 /* or throw an exception */;
}