Consider following code:
main.cpp:
#include <iostream>
typedef void ( * fncptr)(void);
extern void externalfunc(void);
template<void( * test)(void)>
class Bar
{
public:
Bar() { test(); }
};
void localfunc()
{
std::cout << "Hello World" << std::endl;
}
constexpr fncptr alias = localfunc;
extern fncptr externalAlias;
int main(int argc, char* argv[])
{
Bar<localfunc> b;
Bar<alias> b2; // This wouldn't compile if alias wasn't constexpr
Bar<externalfunc> b3;
// Bar<externalAlias> b4;
return 0;
}
and external.cpp:
#include <iostream>
typedef void ( * fncptr)(void);
void externalfunc()
{
std::cout << "Hello external world" << std::endl;
}
fncptr externalAlias = externalfunc;
Now the problem is I need something like the 4th line in the main func to work. I get those function declarations from an external C library so I cannot touch those. Currently the 4th line does not compile. gcc 4.6 says “it must be the address of a function with external linkage”. In fact it does also say this if you make alias not constexpr, so the actual meaning (I think) should be interpreted as: “I don’t know for 100% sure the function address you’re giving me is constant which I need for instantiating this template”. Is there any way around this as i cannot declare externalalias as constexpr in main.cpp?
Before you come with alternate solutions: I am already trying to get this work by just passing the function pointers through the constructor and save them locally but I am still interested if I could get make the template version to work :).
The names
aliasandexternAliasare not functions! They are pointers to functions and as such mutable. You cannot use mutable objects as template arguments because the template arguments need to be resolved at compile time. There are two things you can do, however:All this said, what are you actually trying to achieve? Are you sure you don’t just want something like
std::function<void(void)>? I realize that this is used for type erasure while you seem to have the opposite target and turn function pointers into unique types. However, the way you go about it seems that this isn’t really what you intend to do.Here is an example of how the second option could look like:
The fact that
f()andg()end up being implemented in the same translation unit is entirely immaterial: you can move them somewhere else without any problems.