如何通过引用和指针向函数传递参数?
我有一个示例,其中我尝试调用
CFoo
类的两个写入函数之一。如果我指定两个用逗号分隔的“参数包”const Args1... a, const Args0... b
,则该示例将编译,但如果我指定调用 OnFoo(&CFoo::write, ....);
,那么它将仅适用于两种情况之一。如果我交换“参数包”const Args1... a, const Args0... b
那么图片将完全相反,另一个调用将起作用。
如何才能使这两个调用都起作用,或者将两个“参数包”替换为一个,以便我可以通过引用和指针传递参数?
class CFoo
{
public:
static void write(const char& a, const char& b, const char& c)
{
}
static void write(const char* a, const char* b, const char* c)
{
}
};
#define TYPE_FUNCTION const Args1*... a, const Args0&... b // Work for call with reference
// #define TYPE_FUNCTION const Args0&... a, const Args1*... b // Work for call with point
template <class... Args0, class... Args1> void OnFoo(void (*func)(TYPE_FUNCTION), TYPE_FUNCTION)
{
}
int main(int argc, char** argv)
{
OnFoo(&CFoo::write, '1', '1', '1');
// OnFoo(&CFoo::write, "1", "1", "1");
return 0;
}
第一个案例
class CFoo
{
public:
static void write(const char& a, const char& b, const char& c)
{
}
static void write(const char* a, const char* b, const char* c)
{
}
};
#define TYPE_FUNCTION const Args1*... a, const Args0&... b // Work for call with reference
template <class... Args0, class... Args1> void OnFoo(void (*func)(TYPE_FUNCTION), TYPE_FUNCTION)
{
}
int main(int argc, char** argv)
{
OnFoo(&CFoo::write, '1', '1', '1');
OnFoo(&CFoo::write, "1", "1", "1"); // Error
return 0;
}
错误:
main.cpp: In function 'int main(int, char**)':
main.cpp:24:38: error: no matching function for call to 'OnFoo(<unresolved overloaded function type>, const char [2], const char [2], const char [2])'
24 | OnFoo(&CFoo::write, "1", "1", "1");
| ^
main.cpp:17:48: note: candidate: 'template<class ... Args0, class ... Args1> void OnFoo(void (*)(const Args1* ..., const Args0& ...), const Args1* ..., const Args0& ...)'
17 | template <class... Args0, class... Args1> void OnFoo(void (*func)(TYPE_FUNCTION), TYPE_FUNCTION)
| ^~~~~
main.cpp:17:48: note: template argument deduction/substitution failed:
main.cpp:24:38: note: mismatched types 'const Args0&' and 'const char*'
24 | OnFoo(&CFoo::write, "1", "1", "1");
| ^
main.cpp:24:38: note: inconsistent parameter pack deduction with 'char' and 'char [2]'
第二个案例
class CFoo
{
public:
static void write(const char& a, const char& b, const char& c)
{
}
static void write(const char* a, const char* b, const char* c)
{
}
};
#define TYPE_FUNCTION const Args1&... a, const Args0*... b // Work for call with reference
template <class... Args0, class... Args1> void OnFoo(void (*func)(TYPE_FUNCTION), TYPE_FUNCTION)
{
}
int main(int argc, char** argv)
{
OnFoo(&CFoo::write, '1', '1', '1'); // Error
OnFoo(&CFoo::write, "1", "1", "1");
return 0;
}
错误:
main.cpp:23:42: error: no matching function for call to 'OnFoo(<unresolved overloaded function type>, char, char, char)'
23 | OnFoo(&CFoo::write, '1', '1', '1');
| ^
main.cpp:17:52: note: candidate: 'template<class ... Args0, class ... Args1> void OnFoo(void (*)(const Args1& ..., const Args0* ...), const Args1& ..., const Args0* ...)'
17 | template <class... Args0, class... Args1> void OnFoo(void (*func)(TYPE_FUNCTION), TYPE_FUNCTION)
| ^~~~~
main.cpp:17:52: note: template argument deduction/substitution failed:
main.cpp:23:42: note: mismatched types 'const Args0*' and 'const char&'
23 | OnFoo(&CFoo::write, '1', '1', '1');
| ^
main.cpp:23:42: note: mismatched types 'const Args0*' and 'char'
第一种情况和第二种情况的区别在于我交换了通过引用和指针传递的“参数包”。
您不能将重载集作为参数传递。
所以函数参数应该是不可推导的,
那么你可能会有函数参数,具体取决于其他参数,例如:
template <class... Args>
void OnFoo(std::conditional_t<(std::is_pointer_v<std::decay_t<Args>> && ...),
void(*)(std::decay_t<Args>...),
void(*)(const Args&...)>,
Args&&...)
{
// ...
}
您可以使用
ARGS
的类型信息执行以下操作,以便找到 CFoo::write
所需的重载版本:
#include <iostream>
class CFoo
{
public:
static void write (char a, char b, char c)
{
std::cout << "version1: " << a << " " << b << " " << c << "\n";
}
static void write (const char* a, const char* b, const char* c)
{
std::cout << "version2: " << a << " " << b << " " << c << "\n";
}
};
template <typename...ARGS>
void OnFoo (void (*fct)(ARGS...), ARGS...args)
{
fct (args...);
}
int main (int argc, char** argv)
{
OnFoo (&CFoo::write, '1', '2', '3' );
OnFoo (&CFoo::write, "11", "22", "33");
return 0;
}