我試圖用不同的參數和返回類型創建函數的映射。所以,爲了做到這一點,我已經搜索了很多通過計算器,我覺得我得到了我所需要的,但不完全...從指針調用可變參數模板以提升:: any
背景:
從this後,從答案pmr是我需要的最準確的解決方案。所以,我已經擴大了函數調用到一個可變模板(我希望)。所以,這裏是我的只是調用的版本(AnyCaller類的其餘部分完全一樣):
template<typename Ret, typename ...Args>
Ret call(const std::string& s, Args&&... arg) {
// we have to assume that our users know what we are actually returning here
const boost::any& a = calls[s];
return boost::any_cast< std::function<Ret(Args...)> >(a)(std::forward<Args>(arg)...);
}
而且它編譯OK。現在,這些都是我曾經用來測試類的三個功能:
int foo() { MessageBoxW(nullptr, L"Helolo VOID", L"Info", NULL); return 1; }
double foo2(std::wstring str) { MessageBoxW(nullptr, str.data(), L"Info", NULL); return double(4.5); }
UINT foo3(std::wstring str1, std::wstring str2)
{
std::wstring strBuffer;
strBuffer = str1;
strBuffer += L"==>";
strBuffer += str2;
MessageBoxW(nullptr, strBuffer.data(), L"Info", NULL);
return 4;
}
所以,第一個具有INT(無效),第二雙(STD :: wstring的)的簽名和第三個double(std :: wstring,std :: wstring)。現在
,這是測試代碼:
AnyCaller c;
c.add("foo1", std::function<int(void)>(foo));
c.add("foo2", std::function<double(std::wstring)>(foo2));
c.add("foo3", std::function<UINT(std::wstring, std::wstring)>(foo3));
c.call<int>("foo1");
c.call<double, std::wstring>("foo2", std::wstring(L"foo2!!!").data());
c.call<UINT, std::wstring, std::wstring>("foo3", std::wstring(L"foo3!!!").data(), std::wstring(L"---foo3!!!").data());
,一切都運行平穩:)
所以,但這種好的工作,我真正需要的是增加了函數成員的支持。基本上,我所做的就是創建一個類一個與完全相同的三種功能和幾個測試目的:
class A
{
public:
int foo() { MessageBoxW(nullptr, L"Helolo VOID", L"Info", NULL); return 1; }
double foo2(std::wstring str) { MessageBoxW(nullptr, str.data(), L"Info", NULL); return double(4.5); }
UINT foo3(std::wstring str1, std::wstring str2)
{
std::wstring strBuffer;
strBuffer = str1;
strBuffer += L"==>";
strBuffer += str2;
MessageBoxW(nullptr, strBuffer.data(), L"Info", NULL);
return 4;
}
std::wstring foo4(VOID) { return std::wstring(L"foo4"); }
std::wstring foo5(std::wstring strData) { return (strData + L"--foo5"); }
VOID foo6(VOID) { ; }
};
但我無法得到這個工作。我的第一個問題是指針添加到成員函數:
A a;
c.add("foo1", std::function<int(void)>(&A::foo)); // => Not valid
c.add("foo1", std::function<int(void)>(&a.foo)); // => Not valid
c.add("foo1", &a.foo); // => Not valid
c.add("foo1", a.foo); // => Not valid
c.add("foo1", ?????); //What in heaven goes here?
顯然必須是某種來自一個轉換,但我無法想象...
當然,在這之後,我需要做的實際調用:
int nRet = c.call<int>("foo1");
由於任何人,可以幫助:__)
PS:我不能做靜態成員,如果這是一個解決方案...
PS2:我使用VS2013 ...
SOLUTION:
感謝@Kiroxas,@Praetorian和this文章的評論,我已經出來了一個不涉及可變模板的解決方案。
這是我的測試類A
和B
:
class A
{
public:
int foo1() { MessageBoxW(nullptr, L"Helolo VOID", L"Info", NULL); return 1; }
int foo2(std::wstring str) { MessageBoxW(nullptr, str.data(), L"Info", NULL); return 5; }
int foo3(std::wstring str1, std::wstring str2)
{
std::wstring strBuffer;
strBuffer = str1;
strBuffer += L"==>";
strBuffer += str2;
MessageBoxW(nullptr, strBuffer.data(), L"Info", NULL);
return 4;
}
};
class B
{
public:
std::wstring foo4(VOID) { return std::wstring(L"foo4"); }
std::wstring foo5(std::wstring strData) { return (strData + L"--foo5"); }
VOID foo6(VOID) { ; }
double foo7(std::wstring str1, int nNum)
{
std::wstring strBuffer;
strBuffer = str1;
strBuffer += L"==>";
strBuffer += std::to_wstring(nNum);
MessageBoxW(nullptr, strBuffer.data(), L"Info", NULL);
return double(3.1415);
}
};
這是將它們插入到一個數組,並呼籲他們:)我的理想的解決方案。將它們插入到地圖中的代碼,所以,只要我所有的工作,我會再次更新!該職位。
typedef struct
{
UINT ID;
std::wstring NAME;
boost::any Func;
} funcs;
funcs CallBackItems[] =
{
//From class A
{ 0, L"foo1", std::function<int(void)>(std::bind(&A::foo1, a)) },
{ 1, L"foo2", std::function<int(std::wstring)>(std::bind(&A::foo2, a, std::placeholders::_1)) },
{ 2, L"foo3", std::function<int(std::wstring, std::wstring)>(std::bind(&A::foo3, a, std::placeholders::_1, std::placeholders::_2)) },
//From class B
{ 3, L"foo4", std::function<std::wstring(void)>(std::bind(&B::foo4, b)) },
{ 4, L"foo5", std::function<std::wstring(std::wstring)>(std::bind(&B::foo5, b, std::placeholders::_1)) },
{ 5, L"foo6", std::function<void(void)>(std::bind(&B::foo6, b)) },
{ 6, L"foo7", std::function<double(std::wstring, int)>(std::bind(&B::foo7, b, std::placeholders::_1, std::placeholders::_2)) }
};
int nResult = -1;
std::wstring wstrResult = L"";
double dResult = 0.0;
//class A
nResult = boost::any_cast<std::function<int(void)>>(CallBackItems[0].Func)();
nResult = boost::any_cast<std::function<int(std::wstring)>>(CallBackItems[1].Func)(L"foo2");
nResult = boost::any_cast<std::function<int(std::wstring, std::wstring)>>(CallBackItems[2].Func)(L"foo", L"3");
//class B
wstrResult = boost::any_cast<std::function<std::wstring(void)>>(CallBackItems[3].Func)();
wstrResult = boost::any_cast<std::function<std::wstring(std::wstring)>>(CallBackItems[4].Func)(L"foo5");
boost::any_cast<std::function<void(void)>>(CallBackItems[5].Func)();
dResult = boost::any_cast<std::function<double(std::wstring, int)>>(CallBackItems[6].Func)(L"foo", 7);
函數成員需要一個對象作爲參數,所以使用std :: bind將你的對象'a'綁定到你的函數。比如'c.add(「foo1」,std :: function(std :: bind(&A :: foo,std :: ref(a)));' –
Kiroxas
謝謝@Kiroxas!可悲的是它不適用於VS2013: ( –