![](/img/trans.png)
[英]How to declare and define function that will return one of few custom classes unknown at the compile time?
[英]Is it possible to declare a pointer to a function with unknown (at compile time) return type
我有一個class A
,我希望有一個指向函數的指針作為數據成員:
class A
{
protected:
double (*ptrToFunction) ( double );
public:
...
//Setting function according to its name
void SetPtrToFunction( std::string fName );
};
但是如果我希望ptrToFunction
有時是double
,有時候 - int
,有類似的東西:
//T is a typename
T(*ptrToFunction) ( double );
在這種情況下我該如何申報呢?
受歧視的工會可以為您做到這一點:
class A
{
template<T>
using cb_type = T(double);
protected:
enum {IS_INT, IS_DOUBLE} cb_tag;
union {
cb_type<int> *ptrToIntFunction;
cb_type<double> *ptrToDoubleFunction;
};
public:
...
// Setting function according to its name
void SetPtrToFunction( std::string fName );
};
對於區分聯合的更通用和優雅的解決方案可以應用於C ++ 17中的std::variant
,或者用於早期標准修訂的boost::variant
。
或者,如果要完全忽略返回類型,可以將成員轉換為std::function<void(double)>
並從類型擦除中受益。 Callable
概念將通過指針將調用轉換為static_cast<void>(INVOKE(...))
並丟棄返回值,無論它是什么。
舉例說明 :
#include <functional>
#include <iostream>
int foo(double d) { std::cout << d << '\n'; return 0; }
char bar(double d) { std::cout << 2*d << '\n'; return '0'; }
int main() {
std::function<void(double)> cb;
cb = foo; cb(1.0);
cb = bar; cb(2.0);
return 0;
}
最后,如果您確實關心返回值,但又不想存儲受歧視的聯合。 然后了解聯合和std::function
的行為,你可以結合上面兩種方法。
#include <functional>
#include <iostream>
#include <cassert>
int foo(double d) { return d; }
double bar(double d) { return 2*d; }
struct Result {
union {
int i_res;
double d_res;
};
enum { IS_INT, IS_DOUBLE } u_tag;
Result(Result const&) = default;
Result(int i) : i_res{i}, u_tag{IS_INT} {}
Result(double d) : d_res{d}, u_tag{IS_DOUBLE} {}
Result& operator=(Result const&) = default;
auto& operator=(int i)
{ i_res = i; u_tag = IS_INT; return *this; }
auto& operator=(double d)
{ d_res = d; u_tag = IS_DOUBLE; return *this; }
};
int main() {
std::function<Result(double)> cb;
cb = foo;
auto r = cb(1.0);
assert(r.u_tag == Result::IS_INT);
std::cout << r.i_res << '\n';
cb = bar;
r = cb(2.0);
assert(r.u_tag == Result::IS_DOUBLE);
std::cout << r.d_res << '\n';
return 0;
}
如果您的班級沒有模板(如您的示例中所示),則可以執行以下操作:
template <class T>
struct myStruct
{
static T (*ptrToFunction)(double);
};
看起來您正在使用dlsym
/ GetProcAddress
來獲取函數地址。
在這種情況下,您需要至少2個呼叫站點來消除呼叫的歧義,因為CPU實際上為每個呼叫執行了不同的操作。
enum ReturnType { rtInt, rtDouble };
void SetPtrToFunction( std::string fName , enum ReturnType typeOfReturn );
struct Function {
enum ReturnType rt;
union {
std::function< int(double) > mIntFunction;
std::function< double(double) > mDoubleFunction;
} u;
} mFunction;
因此,需要使用已知的返回類型對函數進行實例化,然后將其與某些標記的union一起使用以獲取正確的函數調用。
int A::doCall( double value ) {
if( mFunction.rt == rtInt ) {
int result = mFunction.mIntFunction( value );
} else if( mFunction.rt == rtDouble ) {
double result = mFunction.mDoubleFunction( value );
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.