How to pass parameters to a function by reference and through a pointer?
I have an example in which I try to call one of two write functions of the CFoo
class. The example compiles if I specify two "parameter pack" const Args1... a, const Args0... b
separated by commas, but if I specify the call OnFoo(&CFoo::write, ....);
then it will only work for one of the two cases. And if I swap the "parameter pack" const Args1... a, const Args0... b
then the picture will be completely opposite, the other call will work.
How can I make both calls work or replace the two "parameter pack" with one, so that I can pass parameters both by reference and through a pointer?
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;
}
First case
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;
}
Error:
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]'
Second case
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;
}
Error:
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'
The difference between the first and second cases is that I swapped the "parameter pack" which is passed by reference and via a pointer.
You cannot pass overload set as parameter.
So function parameter should be non-deducible,
Then you might have function parameter depending of the other parameters, something like:
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&&...)
{
// ...
}