如何防止C 函式多載std::function中的轉換?bool如
class Object final {
public:
Object(bool boolean) : type_(22) {} //#1
Object(const std::function<int(int*, int)> value) : type_(11) {} //#2
int rettype() { return type_; };
private:
int type_;
};
int Println(int *args, int nargs) {
printf("Println\n");
return 0;
}
int main() {
cout << Object(Println).rettype() << endl; // 22
cout << Object(std::function<int(int*, int)>(Println)).rettype() << endl; // 11
}
我想通過而不是呼叫#2,但結果是呼叫#1Object(Println)Object(std::function<int(int*, int)>(Println))
我應該如何實作這一目標?
uj5u.com熱心網友回復:
這里的現代 C 解決方案是
Object::Object(std::invocable<int*, int> auto f)
您并不關心 f 的確切型別是什么-從您考慮std::function<int(int*, int)>和int(*)(int*, int)>可互換的事實中可以清楚地看出這一點。std::invocable比這更籠統:它說任何可呼叫的東西也可以。一個 lambda 也可以。
uj5u.com熱心網友回復:
為什么不是模板化建構式,它要求傳遞的型別可轉換為所需的函式型別?
template<typename F,
typename std::enable_if<std::is_convertible<F, std::function<int(int*, int)>>::value, bool>::type = true>
Object(const F&) : type_(11) {}
(與 . 一起作業-std=c 11。)
優點是您甚至不必std::function在運行時真正擁有任何物件。您只需在編譯時檢查它是否可以轉換為它,然后您可以按原樣使用可呼叫物件,它是函式指標、lambda 或其他。
uj5u.com熱心網友回復:
添加一個函式指標建構式怎么樣?
Object(int (*value)(int*, int)) : Object(std::function<int(int*, int)>(value)) {}
您還可以給函式型別起別名:
using FunctionType = int (*)(int*, int);
Object(FunctionType value) : Object(std::function<int(int*, int)>(value)) {}
uj5u.com熱心網友回復:
檢查編譯器警告
警告:'int Println(int*, int)' 的地址永遠不會是 NULL [-Waddress]
這意味著函式指標會自動自動轉換boolean整數型別。
為了防止這種情況,您可以通過附加型別推導說明符處理函式指標型別。std::function 是一個函式物件,例如函子,而不是原始 C 函式指標,只是有一個轉換建構式
例如:
#include <iostream>
#include <functional>
class Object final {
public:
explicit Object(bool boolean) : type_(22) {} //#1
explicit Object(int(*)(int*,int)) : type_(11) {}
explicit Object(const std::function<int(int*, int)>& value) : type_(11) {} //#2
int rettype() { return type_; };
private:
int type_;
};
int Println(int *args, int nargs)
{
std::cout << "Println" << std::endl;
return 0;
}
struct PrintLine
{
int operator()(int*, int)
{
std::cout << "PrintLine" << std::endl;
return 0;
}
};
int main(int argc, const char** argv)
{
std::cout << Object(Println).rettype() << std::endl; // 11
PrintLine pl;
std::cout << Object(pl).rettype() << std::endl; // 11
std::cout << Object(1).rettype() << std::endl; // 22
return 0;
}
uj5u.com熱心網友回復:
您只能使用一個建構式,但模板并選擇您想要在里面做什么
template<class T>
Object(T t) {
if( std::is_same_v<T,bool>::value )
{
type_ = 22;
}
else
{
type_ = 11;
}
}
演示 17 :https
://wandbox.org/permlink/0eMXkH1l8HzbdfC0
演示 11:https
://wandbox.org/permlink/rOP4JRAP2Ywb1osf
成員初始化串列中的演示 11: https ://wandbox.org/permlink/6QDD4Vdo9TaqU4fT
它只是一個 POC,您可能需要檢查該型別是否是您想要的型別,如果它不是您所期望的則失敗。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/513366.html
標籤:C c 11重载
