0

I am trying to under the class template deduction in C++17.
I wrote a sample class template that can be constructed without specifying the template types. std::unique_ptr can't be constructed without specifying the types.
I need help in understanding why that is the case.

Code compiled using clang 5.0

// Please don't worry about memory leaks, etc. This is sample code anyways.
template<typename T, typename deleter = std::default_delete<T>>
struct Sample
{
T* x_;
deleter func_;

Sample(T* x = nullptr, deleter func = deleter{})
: x_(x)
, func_(func)
{
}
};

auto sample = Sample(new int(10));
std::cout << *(sample.x_) << '\n';

The below code fails to compile.

auto ptr = std::unique_ptr(new int(10)); 
Barry
  • 286,269
  • 29
  • 621
  • 977
Jagannath
  • 3,995
  • 26
  • 30
  • 1
    Would you perhaps care to tell us what the error message is? – Kerrek SB Apr 07 '17 at 01:27
  • 1
    Meta tip: When you're tempted to say "please ignore all the details", try working *with* all the details in place and see if the problem is still unclear. A lot of things are all about the details. – Kerrek SB Apr 07 '17 at 01:42
  • @KerrekSB if it did not compile meaning then isn't that obvious that the compiler complained to provide the template type ? what is there to care or not care ? – Jagannath Apr 07 '17 at 03:02
  • Does this answer your question? [Why can't unique\_ptr's template arguments be deduced?](https://stackoverflow.com/questions/51109767/why-cant-unique-ptrs-template-arguments-be-deduced) – MicroVirus Jun 16 '20 at 10:27

1 Answers1

5

The class template std::unique_ptr is more complicated than your toy example. Its primary ownership-taking constructor takes the form

unique_ptr<T, D>::unique_ptr(pointer p)

where pointer is either D::pointer or remove_reference_t<D>::pointer or T*. So if you wanted to deduce the class template arguments from the constructor, you would first need to know which deleter provides the pointer type, which leads to a circular dependency, and thus you cannot know what T and D should be from the constructor argument. To avoid any accidental misinterpretation, the Standard explicitly requires this constructor not to be usable in template argument deduction (thanks to @T.C. for pointing out the precise wording!).

A simple example is that for an argument of type U* you could deduce either unique_ptr<U> or unique_ptr<U[]>; neither is obviously better, and the wrong choice would be a disaster.

To cut a long story short, the class template arguments of std::unique_ptr are not deducible from constructor arguments, unlike in the case of Sample.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 1
    LWG added specific wording to say that deducing from the `pointer`-taking ctors is ill-formed, precisely due to the `T` vs `T[]` problem. – T.C. Apr 07 '17 at 02:33
  • ok so try compiling without providing template type , if it fails to compile,then provide the types. This is what the feature is all about as far as i understand – Jagannath Apr 07 '17 at 03:01
  • @T.C.: But is there specific wording to effect that, or does it just follow naturally from the existing class definition? I didn't see any explicit guides. – Kerrek SB Apr 07 '17 at 09:52
  • They put it in the constructor's spec, [like this](https://timsong-cpp.github.io/cppwp/unique.ptr.single.ctor#8). – T.C. Apr 07 '17 at 10:02
  • @T.C.: Ah yes, thanks. I'd say that could still be considered part of "this class template is more complicated", but I'll update the post to call out this explicit provision. – Kerrek SB Apr 07 '17 at 10:53