[英]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.