Q:

templated generic setter for unique_ptr member

I'm trying to create a generic setter, supporting values and pointers.
I'm having trouble with pointers. Minimal code that illustrates the main idea:
#include <memory>
#include <variant>

class A{
    int s;
};

template <typename uniq, typename ptr>
void set(uniq &u, const ptr &p){
    u = std::unique_ptr<decltype(*std::declval<ptr>)>(p);
}

int main(){
    std::variant<std::unique_ptr<A>> dd;
    set(dd, new A);
}

Compilation (gcc-7.3.0) fails with 
no matching function for call to ‘std::unique_ptr<A*&& (&)() noexcept, std::default_delete<A*&& (&)() noexcept> >::unique_ptr(A* const&)’

I'm out of ideas about how to get the pointer type...
Also, where does the reference come from? (changing the ptr parameter doesn't solve it)

A:

You just have a typo here:
template <typename uniq, typename ptr>
void set(uniq &u, const ptr &p){
    u = std::unique_ptr<decltype(*std::declval<ptr>)>(p);
    //                                            ^^^
}

std::declval is a function, so the code you're writing is trying to dereference that function type. Which is a valid thing to do! That's how you get A*&& (&)() noexcept
What you want is:
template <typename uniq, typename ptr>
void set(uniq &u, const ptr &p){
    u = std::unique_ptr<decltype(*std::declval<ptr>())>(p);
}

Which you can write a lot simpler by just directly using the name p:
template <typename uniq, typename ptr>
void set(uniq &u, const ptr &p){
    u = std::unique_ptr<decltype(*p)>(p);
}

But this probably isn't actually correct since decltype(*p) would typically have a reference type, and you have to remove it:
template <typename uniq, typename ptr>
void set(uniq &u, const ptr &p){
    u = std::unique_ptr<std::remove_reference_t<decltype(*p)>>(p);
}

Now, this code really only works with a raw pointer (you'd have to move a unique_ptr and you can't convert a shared_ptr to a unique_ptr), so you could more clearly express that in the function signature which also makes the body much easier to write:
template <typename uniq, typename T>
void set(uniq &u, T* p){
    u = std::unique_ptr<T>(p);
}

Which ultimately begs the question of why you would want to write:
set(dd, new A);

instead of:
dd = std::make_unique<A>();

anyway? The 2nd is far superior. 

A:

To construct std::unique_ptr explicitly:
template <typename uniq, typename ptr>
void set(uniq &u, const ptr &p)
{
    using T = std::remove_pointer_t<ptr>;
    u = std::unique_ptr<T>(p);
}

