簡體   English   中英

如何使我的 function 根據使用 C++ 中的模板調用的類型返回不同的結果

[英]How do I make my function return different results depending on type it's been called using templates in C++

我一直在尋找我的問題的答案很長一段時間,但找不到任何有效的方法。

基本上,我有一個二叉搜索樹和一個搜索 function:

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);
} 

我想根據調用它的類型返回不同的東西。 例如,如果我將 function 稱為Search<bool>() ,我希望它返回真或假,但如果我調用Search<Node*> ,我希望它返回一個指針。 它應該看起來像這樣:

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;
}

我什至不確定這里的模板是否是通往 go 的正確方式,但是任何有關實施的提示都將不勝感激。

如評論中所述,從 API 可用性的角度來看,基於返回類型的重載通常不是一個好主意(並且由於 C++ 不支持開箱即用,因此無論如何都需要一些技巧)。

相反,使用兩個不同的 function 名稱,這些名稱明確說明了它們的作用:

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;
}

此外,這些函數的公共 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 */;
} 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM