5

Is there any way to get a member function pointer to the copy constructor of a class? I know how to define and use a normal member function pointer, but I can't seem to figure out a way to get it.

rubenvb
  • 69,525
  • 30
  • 173
  • 306
  • 6
    You cannot. Constructors do not have names. – Kerrek SB Oct 27 '16 at 16:23
  • You can't but depending on what you want to do, you might be able to find a workaround using a lamda. I.e. putting it in the lamda. – Makaronodentro Oct 27 '16 at 16:31
  • 8
    This sounds like an [XY problem](http://xyproblem.info/). Suppose you somehow managed to obtain a pointer to a constructor (not that you can) - how would you use it? What's the actual problem you are trying to solve? – Igor Tandetnik Oct 27 '16 at 16:36
  • 1
    @Makaronodentro - minor point, but it's spelled "lambda", not "lamda". – Pete Becker Oct 27 '16 at 16:56
  • @rubenvb Why do you need it? With the advent of lambdas the practice passing of member functions has largely gone the way of the record player. It's likely that there is a better way to approach your problem. – Jonathan Mee Oct 27 '16 at 17:44
  • 2
    if you could, how would you plan to use it? I.e the syntax for mfp is `(someObject.*mfp)(args)`. how would you use the copy constructor member function pointer to construct a new object with that syntax? – Johannes Schaub - litb Oct 27 '16 at 18:14
  • @Johannes right, I'm asking the wrong question. I just need a copiable `default_copy` class that prevents slicing that I can use in my `value_ptr`. – rubenvb Oct 28 '16 at 17:48

1 Answers1

3

According to the C++ standard, "the address of a constructor shall not be taken," so it's just not possible to do what you're asking. However, there's a simple workaround. The below code returns a function pointer to a function that creates a copy of it's input.

template<class obj> auto GetCopyConstructor() -> obj(*)(const obj&) 
{
    return +[](const obj& o) { return obj(o); };
}    
struct foo
{
    std::string msg;
    foo(const std::string& my_msg) { msg = my_msg; }
    foo(const foo&) = default;
};
int main()
{
    auto make_copy = GetCopyConstructor<foo>();
    foo a("Hello, world");
    foo b = make_copy(a);
    std::cout << b.msg << std::endl;
}

Alternatively: (A simplification that also covers additional use cases)

template<class obj> obj Copy(const obj& o) { return obj(o); }
template<class obj> obj* CopyNew(const obj& o) { return new obj(o); }
template<class obj> obj CopyFromPtr(const obj* o) { return obj(*o); }
template<class obj> obj* CopyNewFromPtr(const obj* o) { return new obj(*o); }
template<class obj> void* WhyWouldYouEvenWantToDoThis(const void* o) 
{ return new obj(*(obj*)o); }
int main()
{
    foo(*make_copy)(const foo&) = Copy<foo>;
    foo a("Hello, world");
    foo b = make_copy(a);
    std::cout << b.msg << std::endl;
}
J. Antonio Perez
  • 8,918
  • 16
  • 37
  • The only missing lines are #include and #include , and the code works in both C++11 and C++14 using the GCC compiler. What problems are you having? – J. Antonio Perez Oct 27 '16 at 20:11
  • [Never mind](http://stackoverflow.com/questions/18889028/a-positive-lambda-what-sorcery-is-this). Learned something new today. – StoryTeller - Unslander Monica Oct 27 '16 at 20:22
  • The + should not be necessary, not sure why it's there? It should trigger an implicit conversion upon return just fine without it. – Nir Friedman Oct 27 '16 at 20:35
  • 2
    @NirFriedman the `+` would be relevant if the trailing return type were omitted (in which case the return type is deduced from the argument of the return statement, without applying the conversion of lambda to function-pointer) – M.M Oct 27 '16 at 23:52
  • Hmm this would be fine if I could store the results of different GetCopyConstructor calls in one type. I guess making the return type `void*(*)(void*)` would do, but also sidestep the type system :( – rubenvb Oct 28 '16 at 17:26
  • What are you trying to accomplish, exactly? – J. Antonio Perez Oct 28 '16 at 18:08
  • I added more code; hopefully some of it will be useful. – J. Antonio Perez Oct 28 '16 at 18:43
  • You might also mention that, even aside from explicitly not being able to take their addresses, constructors and destructors are not technically functions! – acwaters Oct 28 '16 at 20:30
  • What I was trying to do was this: http://stackoverflow.com/a/40330151/256138. You did point me in the right direction. Note I am not convinced the final construct is useful. I'm quite sure it's not useless though ;). – rubenvb Nov 03 '16 at 21:57