2

I think this code should print "hit" but it doesn't. If you comment out line 6 (the template line), it prints "hit."

#include <iostream>

struct test {
    test() {}

    template<typename = typename std::enable_if<true>::type>
    test(test const & other) {
        std::cout << "hit";
    }
};

int main()
{
  test a;
  test b(a);
}

The standard explicitly indicates this. What's the rationale?

Brent
  • 4,153
  • 4
  • 30
  • 63
  • I tested this in Visual Studio 2017 and https://cpp.sh – Brent Dec 12 '18 at 19:02
  • Maybe because the template function is not a copy constructor, but something masquerading as one? AFAIK, the standard doesn't define the canonical copy constructor as a function that is templated. OK, the duplicate verified my suspicions. – PaulMcKenzie Dec 12 '18 at 19:14
  • https://stackoverflow.com/a/9487897/1848654 – melpomene Dec 12 '18 at 19:19
  • When compiler has to choose between free-function (default copy ctor generated by compiler) and templated ctor (both have the same match), always free-function is called. You can see `hit` only if you remove `const` from signature of templated ctor because `template<> test(test&)` is better match when it is called for non-const object `test a;` than calling default copy ctor which takes `test` by const reference. – rafix07 Dec 12 '18 at 19:26
  • Is constructor inheritance a possible workaround? Two base classes, one has the constructor, one does not, and which is inherited is determined through template resolution. – Brent Dec 12 '18 at 19:27
  • @Brent What are you trying to accomplish with this? There is probably an already existing workaround – NathanOliver Dec 12 '18 at 19:29
  • I have a wrapper class that's templated on a type T. The wrapper class should only be copy constructible if T is. – Brent Dec 12 '18 at 19:29
  • Does the class hold a `T`. If so you already get this. If `T` is not copyable it will automatically mark the wrappers copy constructor as deleted. This is how `std::vector` works. A `std::vector` is copyable but a `std::vector>` isn't. – NathanOliver Dec 12 '18 at 19:33
  • It only holds a T through a pointer. More importantly, if a copy is permitted, the default copy constructor doesn't have the needed behavior. – Brent Dec 12 '18 at 19:36
  • I think another work around might be to have a new class that when copied carries out the needed operations. Add an instance of this class to the wrapper, and let the default copy constructor do its thing. Put a T in the wrapper class to control whether that default copy constructor is created. – Brent Dec 12 '18 at 19:41
  • 1
    @Brent You could also specialize the entire class. Take a look at this: http://coliru.stacked-crooked.com/a/40807e3483fc075e – NathanOliver Dec 12 '18 at 19:58

0 Answers0