[英]Enable template if functor passed as argument takes no argument
我試圖為模板函數定義兩個重載。 如果functor作為參數傳遞沒有參數,則會生成第一個重載,否則會生成第二個重載。 我開始像這樣實現:
template <typename R, typename... Types>
constexpr size_t argumentCount(R (*f)(Types...))
{
return sizeof...(Types);
}
template <typename Function>
typename std::enable_if<argumentCount<Function>() == 0, int>::value = 0 > callFunc(Function fu)
{
fu();
}
template <typename Function, typename... Params>
typename std::enable_if<argumentCount<Function>() == 0, int>::value = 0 > callFunc(Function fu, Params... params)
{
fu(std::forward<decltype(params)>(params)...);
}
由於包括解析錯誤在內的多種原因,這無法編譯。我想做的是,
callFunc([](){});
將callFunc([](int value1,int value2){});
調用重載1 callFunc([](int value1,int value2){});
將調用重載2。
我怎樣才能做到這一點?
您可以將檢測慣用法與std::void_t
和std::declval
來檢測此類功能。
template <typename FuncT>
using invocable_without_args_t = std::void_t<decltype(std::declval<FuncT>()())>;
更多信息請點擊此處 ; 這篇文章幫助我了解了它的工作原理。
template <typename R, typename... Types>
constexpr size_t argumentCount(R (*f)(Types...))
{
return sizeof...(Types);
}
template <typename Function>
typename std::enable_if<argumentCount<Function>() == 0, int> callFunc(Function fu)
{
fu();
}
template <typename Function, typename... Params>
typename std::enable_if<argumentCount<Function>() == 0, int> callFunc(Function fu, Params... params)
{
fu(std::forward<decltype(params)>(params)...);
}
Types...
可以為空。 template <typename Function, typename... Params>
auto callFunc(Function fu, Params... params)
{
fu(std::forward<decltype(params)>(params)...);
}
效果很好。
如果你可以添加一個間接級別......那么使用tag-dispatching而不是SFINAE呢?
我的意思是,如下
#include <iostream>
#include <type_traits>
template <typename F>
void callFunc_helper (F fu, std::true_type)
{
std::cout << "zero version" << std::endl;
fu();
}
template <typename F, typename... Prs>
void callFunc_helper (F fu, std::false_type, Prs && ... params)
{
std::cout << "non zero version" << std::endl;
fu(std::forward<Prs>(params)...);
}
template <typename F, typename... Prs>
void callFunc (F fu, Prs && ... params)
{ callFunc_helper(fu, std::integral_constant<bool, 0u == sizeof...(Prs)>{},
std::forward<Prs>(params)...); }
int main ()
{
callFunc([]{});
callFunc([](int, int){}, 0, 1);
}
顯然你可以使用std::integral_constant<bool, 0u == argumentCount<Function>()>{}
如果你真的想檢查函數參數的數量而不是以下參數的數量(但為什么呢?)。
如果您需要兩個模板函數,只需編寫它們:
#include <iostream>
template <class R>
void callFunc(R (*f)()) {
std::cout << "Called no-arg template\n";
f();
}
template <class R, class T, class... Types, class... Params>
void callFunc(R (*f)(T, Types...), Params... params) {
std::cout << "Called multi-arg template\n";
f(params...);
}
void g() {
std::cout << "Called g\n";
}
void h(int) {
std::cout << "Called h\n";
}
int main() {
callFunc(g);
callFunc(h, 3);
return 0;
}
輸出:
[temp]$ clang++ -std=c++11 test.cpp
[temp]$ ./a.out
Called no-arg template
Called g
Called multi-arg template
Called h
[temp]$
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.