0

Before closing this as a duplicate (since there are several questions like this which did actually explain how to achieve the solution - this, and this), I did go through the similar questions, but after doing the same I still get hit by the 'enable_if' cannot be used to disable this declaration. So here is my example:

#include <iostream>
#include <memory>
#include <type_traits>

namespace std
{
    
template<typename>
struct is_shared_ptr : std::false_type {};

template<typename T>
struct is_shared_ptr<std::shared_ptr<T>> : std::true_type {};

}

template<typename T>
struct Foo
{
    template<typename ... Arguments>
    Foo(Arguments&& ... arguments, std::enable_if_t<!std::is_shared_ptr<T>::value>* = nullptr)
    {
        std::cout << "ctor without shared_ptr\n";
    }
    
    template<typename ... Arguments>
    Foo(Arguments&& ... arguments, std::enable_if_t<std::is_shared_ptr<T>::value>* = nullptr)
    {
        std::cout << "ctor with shared_ptr\n";
    }

    T value_;
};

int main(int argc, char **argv)
{
    Foo<int> a;
    Foo<std::shared_ptr<int>> b;
    return 0;
}

Here is the link to this example on coliru. What I want to achieve is being able to initialise value_ with make shared when T is std::shared_ptr. The other questions show that moving the std::enable_if deduction to function parameters work, but not in my case. Am I missing/overlooked something in the examples?

Rudolfs Bundulis
  • 11,636
  • 6
  • 33
  • 71
  • 2
    Once you have fixed `T` by the **class**, `std::enable_if_t::value>*` would be a hard failure (it is not substitution of template argument of the function). – Jarod42 Jan 10 '22 at 12:45
  • @Jarod42 Ahh, yeah both examples have a `bool` template type, not an actual `typename`. So in this case I cannot achieve the result? – Rudolfs Bundulis Jan 10 '22 at 12:47
  • 1
    As an aside, adding declarations to namespace `std` produces undefined behavior. `is_shared_ptr` should be in your own namespace. – StoryTeller - Unslander Monica Jan 10 '22 at 12:49
  • Possibly something like `typename U = T, std::enable_if_t>* = 0>` – Jarod42 Jan 10 '22 at 12:49
  • 1
    Adding and additional "artificial" type template parameter set to `T` by default and applying SFINAE to this parameter should work. Live demo: https://godbolt.org/z/er66cnT7r. One of many relevant questions: https://stackoverflow.com/q/30953248/580083. – Daniel Langr Jan 10 '22 at 12:50
  • @Jarod42 yeah just thought of that myself and tried it - it works, but seems weird that I need to do this kind of looping around. If you post this as an answer I'll happily accept that. – Rudolfs Bundulis Jan 10 '22 at 12:50
  • in c++20 `requires` allow simpler syntax :-) – Jarod42 Jan 10 '22 at 12:51
  • @StoryTeller-UnslanderMonica yes I know, this was just a quick sample. – Rudolfs Bundulis Jan 10 '22 at 12:51
  • @Jarod42 yes, I saw how `requires` would fix that while brosing SO, but I'm stuck with msvc 2017 (and as far as I googled msvc has `requires` only in 2022). – Rudolfs Bundulis Jan 10 '22 at 12:52

0 Answers0