簡體   English   中英

如何在編譯時通過名稱/指針獲取函數類型的模板參數默認值?

[英]How to get type of a function by its name/pointer at compile-time for a template parameter default value?

有什么方法可以在編譯時通過其名稱/指針獲取函數類型,並將其用作模板參數的默認值?

考慮以下代碼:

template <typename TreeNode>
void default_visitor(TreeNode* node)
{
    std::cout << node->data << std::endl;
}

template <typename TreeNode, typename Visitor>
void binary_tree_traverse(TreeNode* root, Visitor visitor)
{
    /* some tree traversal calling the visitor for a node: */
    visitor(root);
}

之后,可以使用任何訪問者類型調用binary_tree_traverse() ,例如:

// call with lambda
binary_tree_traverse(root,
                     [](BinaryTreeNode *node)
                     { std::cout << node->data << std::endl; });

// call with default_visitor() or anything else...
binary_tree_traverse(root, default_visitor<BinaryTreeNode>);

但是,我也希望能夠省略visitor參數並像下面這樣簡單地調用函數:

binary_tree_traverse(root);

在這種情況下,它的行為就像使用default_visitor<>調用一樣。

問題是如何相應地更改模板功能定義? 類似於以下內容將是理想的解決方案:

template <typename TreeNode,
          typename Visitor = ?typeof? default_visitor<TreeNode>>
void binary_tree_traverse(TreeNode* root,
                          Visitor visitor = default_visitor<TreeNode>)
{
    visitor(root);
}

任何想法如何做到這一點? 可能嗎?

另一種解決方案可以是使用模板專門化(或為此專有名稱是什么?)並定義函數的額外版本(在這種情況下,可以刪除第二個函數參數,但是思想是相同的):

template<typename TreeNode>
using typeof_default_visitor = void(*)(TreeNode*);

template <typename TreeNode>
void binary_tree_traverse(TreeNode* root,
                          typeof_default_visitor<TreeNode> visitor = default_visitor<TreeNode>)
{
    // call the generic version:
    binary_tree_traverse<TreeNode, typeof_default_visitor<TreeNode>>(root, visitor);
}

但這看起來並不好,不是嗎? 為了使用默認參數,額外的[dummy]函數似乎是一個過大的殺傷力。 解決此問題的正確方法(真正的C ++)是什么? 這里有什么選擇?

重載,但沒有第二個參數,而不是默認值。 不,這不是〜overkill〜,這是最簡單的解決方案。

template <typename Node, typename Fn>
void foo(Node* root, Fn&& func) {
    // ...
}

template <typename Node>
void foo(Node* root) {
    foo(root, some_default_func);
}

我想你已經很接近了:

template <typename TreeNode,
          typename Visitor = decltype(default_visitor<TreeNode>)>
void binary_tree_traverse(TreeNode* root,
                          Visitor visitor = default_visitor<TreeNode>)
{
    visitor(root);
}

decltype和默認參數:

template <typename TreeNode, typename Visitor = decltype(&default_visitor<TreeNode>)>
void binary_tree_traverse(TreeNode* root, Visitor visitor = &default_visitor<TreeNode>)
{
    /* some tree traversal calling the visitor for a node: */
    visitor(root);
}

如果那不可用(如MSVC),則只需重載該函數即可。

只是重載方法。

template <typename TreeNode,
          typename Visitor>
void binary_tree_traverse(TreeNode* root,
                          Visitor visitor)
{
    visitor(root);
}
template <typename TreeNode>
void binary_tree_traverse(TreeNode* root)
{
    binary_tree_traverse(root, default_visitor<TreeNode>);
}

暫無
暫無

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

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