I currently have a map<int, std::wstring>, but for flexibility, I want to be able to assign a lambda expression, returning std::wstring as value in the map.
So I created this template class:
template <typename T>
class ValueOrFunction
{
private:
std::function<T()> m_func;
public:
ValueOrFunction() : m_func(std::function<T()>()) {}
ValueOrFunction(std::function<T()> func) : m_func(func) {}
T operator()() { return m_func(); }
ValueOrFunction& operator= (const T& other)
{
m_func = [other]() -> T { return other; };
return *this;
}
};
and use it like:
typedef ValueOrFunction<std::wstring> ConfigurationValue;
std::map<int, ConfigurationValue> mymap;
mymap[123] = ConfigurationValue([]() -> std::wstring { return L"test"; });
mymap[124] = L"blablabla";
std::wcout << mymap[123]().c_str() << std::endl; // outputs "test"
std::wcout << mymap[124]().c_str() << std::endl; // outputs "blablabla"
Now, I don't want to use the constructor for wrapping the lambda, so I decided to add a second assignment operator, this time for the std::function:
ValueOrFunction& operator= (const std::function<T()>& other)
{
m_func = other;
return *this;
}
This is the point where the compiler starts complaining. The line mymap[124] = L"blablabla"; suddenly results in this error:
error C2593: 'operator = is ambiguous'
IntelliSense gives some more info:
more than one operator "=" matches these operands: function
"ValueOrFunction::operator=(const std::function &other) [with
T=std::wstring]" function "ValueOrFunction::operator=(const T
&other) [with T=std::wstring]" operand types are: ConfigurationValue =
const wchar_t
[10] c:\projects\beta\CppTest\CppTest\CppTest.cpp 37 13 CppTest
So, my question is, why isn't the compiler able to distinguish between std::function<T()> and T? And how can I fix this?
The basic problem is that std::function has a greedy implicit constructor that will attempt to convert anything, and only fail to compile in the body. So if you want to overload with it, either no conversion to the alternative can be allowed, of you need to disable stuff that can convert to the alternative from calling the std::function overload.
The easiest technique would be tag dispatching. Make an operator= that is greedy and set up for perfect forwarding, then manually dispatch to an assign method with a tag:
template<typename U>
void operator=(U&&u){
assign(std::forward<U>(u), std::is_convertible<U, std::wstring>());
}
void assign(std::wstring, std::true_type /*assign_to_string*/);
void assign(std::function<blah>, std::false_type /*assign_to_non_string*/);
basically we are doing manual overload resolution.
More advanced techniques: (probably not needed)
Another approach would be to limit the std::function = with SFINAE on the argument being invoked is valid, but that is messier.
If you have multiple different types competing with your std::function you have to sadly manually dispatch all of them. The way to fix that is to test if your type U is callable with nothing and the result convertible to T, then tag dispatch on that. Stick the non-std::function overloads in the alternative branch, and let usual more traditional overloading to occur for everything else.
There is a subtle difference in that a type convertible to both std::wstring and callable returning something convertible to T ends up being dispatched to different overloads than the original simple solution above, because the tests used are not actually mutually exclusive. For full manual emulation of C++ overloading (corrected for std::functions stupidity) you need to make that case ambiguous!
The last advanced thing to do would be to use auto and trailing return types to improve the ability of other code to detect if your = is valid. Personally, I would not do this before C++14 except under duress, unless I was writing some serious library code.
Both std::function and std::wstring have conversion operators that could take the literal wide string you are passing. In both cases the conversions are user defined and thus the conversion sequence takes the same precedence, causing the ambiguity. This is the root cause of the error.
Related
I'm trying to write an overloaded method that returns non-const result only when both the object on which it is called is non-const and iterator passed in the argument is non-const.
(Think of it like the standard methods begin() and begin() const that additionally take an iterator argument.)
I made a version for normal iterators with no problems.
However, for some reason, when I'm trying to do the same for reverse iterators, I get a compilation error about an ambiguous function call.
Here's a minimal example:
#include <vector>
class Foo
{
public:
void bar(std::vector<int>::iterator x) {}
void bar(std::vector<int>::const_iterator x) const {}
void baz(std::vector<int>::reverse_iterator x) {}
void baz(std::vector<int>::const_reverse_iterator x) const {}
};
int main()
{
std::vector<int> v;
Foo foo;
foo.bar(v.cbegin()); // OK
foo.baz(v.crbegin()); // ambiguous
}
For some reason it compiles if I remove const from the second method baz.
It also works in C++20 but currently I cannot use that version.
live demo
How can I make the function baz work in analogous way to the function bar?
Oh the joys of overloading resolution rules and SFINAE.
The methods are equivalent to free functions:
void bbaz(Foo&,std::vector<int>::reverse_iterator){}
void bbaz(const Foo&,std::vector<int>::const_reverse_iterator){}
and your usage becomes:
int main()
{
std::vector<int> v;
Foo foo;
bbaz(foo,v.crbegin());
}
The arguments do not exactly match either call:
foo is Foo&, not const Foo&
v.crbegin() return vector::const_reverse_iterator which is just a different instantiation of the same std::reverse_iterator template as vector::reverse_iterator.
reverse_iterator->std::reverse_iterator<vector::iterator>
const_reverse_iterator-> std::reverse_iterator<vector::const_iterator>
Cause of ambiguity
Now, the issue is that std::reverse_iterator's ctor is not SFINAE-friendly until C++20:
template< class U >
std::reverse_iterator( const std::reverse_iterator<U>& other );
I.e. there is a viable candidate converting std::reverse_iterator<T> to std::reverse_iterator<U> between any T-U pairs. In this case for T=vector::const_iterator, U=vector::iterator. But of course the template instantiation fails later because it cannot convert const int* to int*.
Since that happens in the template function's body, not the signature, it is too late for SFINAE and overloading considers it a viable candidate function, hence the ambiguity since both calls require one implicit conversion - although only the second one would compile.
This is explained in these answers, making this one essentially a duplicate of that question but it would be IMHO cruel to mark it as such without an explanation which I cannot fit into a comment.
C++20 fixes this omission and SFINAEs that ctor - cppreference:
This overload participates in overload resolution only if U is not the same type as Iter and std::convertible_to<const U&, Iter> is modeled (since C++20)
Solution
As pointed in the comments by #Eljay, forcing const Foo& at the call site is one option, one can use C++17 std::as_const:
#include <utility>
std::as_const(foo).baz(v.crbegin());
Fixing this at definition is more tricky, you could use SFINAE to actually force these overloads but that might be a hassle. #fabian 's solution with adding a third overload without const method qualifier seems easiest to me:
void Foo::baz(std::vector<int>::const_reverse_iterator x) {
return std::as_const(*this).baz(x);
}
It works because now it is a better (exact) match for non-const Foos than the still considered vector::reverse_iterator which would not compile anyway.
I want an object which can wrap a value symantic type and pretend that it is a reference.
Something like this:
int a = 20;
std::list<Wrap<int>> l1;
l1.push_back(a);
std::list<Wrap<int>> l2;
l2.push_back(a);
l2.front() = 10;
cout << l1.front() << endl; // output should be 10
While writing this question it occured to me that a shared_ptr might be what I want. However I am not sure if a pointer symantic object is what I am looking for. Perhaps there is no alternative in the standard library?
std::shared_ptr<int> a = std::make_shared(10);
std::list<std::shared_ptr<int>> l1;
l1.push_back(a);
std::list<std::shared_ptr<int>> l2;
l2.push_back(a);
*(l2.front()) = 20; // not exactly what I wanted to write
cout << *l1.front() << endl; // prints 10
I found std::reference_wrapper but this appears to be the opposite of what I want. It appears to permit a reference type to be used like a value type which is the reverse of what I wanted.
Any thoughts?
Proxy Object
As far as I know, there isn’t such a wrapper in the Standard Library. Fortunately though, you can implement one yourself rather easily.
How to start? Well, we’d like our Wrap<T> to be possibly indistinguishable from a T&. To achieve this, we can implement it as a proxy object. So, we’ll be making a class template storing a T& ref and implement operations one by one:
template<typename T>
struct Wrap
{
private:
T& ref;
public:
// ???
};
Construction
Let’s start with constructors. If we want Wrap<T> to behave like a T& it should be constructible from the same things that T& is constructible. Well then, what is a reference x constructible from?
A non-const lvalue reference like T& x = ...; needs to be constructed from an lvalue of type T. This means that it can be constructed from:
an object of type T
an object of a type derived from T
a different lvalue reference to T
an object convertible to T&
a function call returning T&
A const lvalue reference like const T& x = ...; can also be constructed from a braced-initializer-list or materialized from a temporary, however if we wanted to implement that, then we’d need to actually store a T inside of our class. As such, let’s focus on a non-const reference.
First, let’s implement a constructor from T& which will cover all of the cases shown above:
constexpr Wrap(T& t) noexcept :
ref{t}
{
}
The constructor is constexpr and noexcept because it can be. It is not explicit because we want to be able to use Wrap as transparently as possible.
We need to remember though, that a reference needs to be initializable from a different reference. Because we want our type to behave just like a builtin reference, we need to be able to
initialize a Wrap from a T& (already implemented above)
initialize a Wrap from a different Wrap
initialize a T& from a Wrap
To meet these criteria, we’ll need to implement a conversion operator to T&. If Wrap<T> will be implicitly convertible to T&, then assigning it to a builtin reference will work.
Actually, this:
int x;
Wrap w = x;
Wrap w2 = w;
will also work (ie. w2 will be Wrap<int> rather than a Wrap<Wrap<int>>) because the conversion operator takes precedence.
The implementation of the conversion operator looks like this:
constexpr operator T&() const noexcept
{
return ref;
}
Note that it is constexpr, noexcept and const, but not explicit (just like the constructor).
Miscelaneous operations
Now that we can construct our custom reference wrapper, we’d also like to be able to use it. The natural question is “what can you do with a reference”? Well, builtin references aren’t objects but merely aliases to existing objects. This means that taking the address of the reference actually returns the address of the referent or that you can access members through a reference.
All these things could be implemented, for example by overloading the arrow operator operator-> or the address-of operator operator&. For simplicity though, I will omit implementing these operations and focus only on the most important one: assignment.
Assignment
Firstly, we’d like to be able to assign a Wrap<T> to a T& or a T or basically anything that can be assigned a T. Fortunately, we already got that covered by having implemented the conversion operator.
Now we only need to implement assignment to Wrap<T>. We could be tempted to just write the operator like this:
constexpr T& operator=(const T& t)
{
ref = t;
return ref;
}
constexpr T& operator=(T&& t) noexcept
{
ref = std::move(t);
return ref;
}
Seems fine, right? We have a copy assignment operator and a noexcept move assignment operator. We return a reference as per custom.
Well, the problem is that this implementation is incomplete. The thing is that we don’t check
is T copy-assignable
if it is, then is it nothrow-copy-assignable
is T move-assignable
if it is, then is it nothrow-move-assignable
what is the return type of T’s assignment operator (it could be the customary T&, but it could also theoretically be anything else, like void)
does T have any other assignment operators
This is a lot of cases to cover. Fortunately, we can solve this all by making our assignment operator a template.
Let’s say that the operator will take an object of arbitrary type U as its argument. This will cover both the copy and move assignment operators and any other potential assignment operators. Then, let’s say that the return type of the function will be auto, to let the compiler deduce it. This gives us the following implementation:
template <typename U>
constexpr auto operator=(U u)
{
return (ref = u);
}
Unfortunately though, this implementation is still not complete.
We don’t know if the assignment is noexcept
We don’t distinguish copy assignment and move assignemnt and could potentially be making unnecessary copies.
Is the return type (auto) really correct?
To solve the first issue we can use a conditional noexcept. To check if the assignment operator is noexcept we can either use the type trait std::is_nothrow_assignable_v or the noexcept operator. I think that using the noexcept operator is both shorter and less error-prone, so let’s use that:
template <typename U>
constexpr auto operator=(U u) noexcept(noexcept(ref = u))
{
return (ref = u);
}
To solve the issue of distinguishing copies and moves, instead of taking a U u, we can take a forwarding reference U&& u, to let the compiler deal with all of this. We also need to remember about using std::forward:
template <typename U>
constexpr auto operator=(U&& u) noexcept(noexcept(ref = std::forward<U>(u)))
{
return (ref = std::forward<U>(u));
}
There is a bit of code duplication, but, unfortunately, it is inevitable, unless we’d use std::is_nothrow_assignable_v instead.
Finally, is the return type correct? Well, no. Because C++ is C++, parentheses around the returned value actually change its type (ie. return(x); is different from return x;). To return the correct type, we’ll actually also need to apply perfect forwarding to the returned type as well. We can do this by either using a trailing return type or a decltype(auto) return type. I will use decltype(auto) as it’s shorter and avoids duplicating the function body yet again:
template <typename U>
constexpr decltype(auto) operator=(U&& u) noexcept(noexcept(ref = std::forward<U>(u)))
{
return ref = std::forward<U>(u);
}
Conclusion
Now, finally, we have a complete implementation. To sum things up, here it is all together (godbolt):
template<typename T>
struct Wrap
{
private:
T& ref;
public:
constexpr Wrap(T& t) noexcept :
ref{t}
{
}
constexpr operator T&() const noexcept
{
return ref;
}
template <typename U>
constexpr decltype(auto) operator=(U&& u) noexcept(noexcept(ref = std::forward<U>(u)))
{
return ref = std::forward<U>(u);
}
};
That was quite a bit of C++ type theory to get through to write these 21 lines. Oh, by the way, did I mention value categories...
I am learning about templates in C++, and came across an example where casting to void is used:
template<typename T>
auto func (T const& t) -> decltype( (void)(t.size()), T::size_type() )
{
return t.size();
}
In the explanation it is written that:
The cast of the expression to void is to avoid the possibility of a user-defined comma operator overloaded for the type of the expressions.
My question(s) is/are:
How can a cast to void be used to "avoid the possibility of a user-defined comma operator overloaded for the type of the expressions"? I mean, can anyone give any example where if we don't use void then this code would give an error? For example, let's say we have a class called SomeClass which has overloaded the comma operator. Now, can this become a problem if we don't use void?
Can static_cast be used in this case instead of a C style cast? For example, something like static_cast<void>(t.size()). I am reading examples that use C++17 features, and so I wonder why the author has used a C style cast in this case.
I have read What does casting to `void` really do?, from which I get the impression that if we use (void)x then this means to suppress compiler warnings, and also means "ignore the value of x". But then I can't understand the difference between the expression x and (void)x.
Consider this pathological type:
struct foo {
struct size_type {
bool operator,(size_type) { return false;}
};
size_type size() { return {};}
};
It does have a size_type and it does have a size() method. However, without the cast to void, the template does not deduce the right return type, because decltype( (t.size()), typename T::size_type() ) is bool :
#include <type_traits>
template<typename T>
auto func (T const& t) -> decltype( (t.size()), typename T::size_type() )
{
return t.size();
}
struct foo {
struct size_type {
bool operator,(size_type) { return false;}
};
size_type size() const { return {};}
};
int main()
{
func(foo{});
}
Results in error:
<source>:6:8: error: no viable conversion from returned value of type 'foo::size_type' to function return type 'decltype((t.size()) , typename foo::size_type())' (aka 'bool')
return t.size();
^~~~~~~~
<source>:20:4: note: in instantiation of function template specialization 'func<foo>' requested here
func(foo{});
^
1 error generated.
ASM generation compiler returned: 1
<source>:6:8: error: no viable conversion from returned value of type 'foo::size_type' to function return type 'decltype((t.size()) , typename foo::size_type())' (aka 'bool')
return t.size();
^~~~~~~~
<source>:20:4: note: in instantiation of function template specialization 'func<foo>' requested here
func(foo{});
^
A static_cast can be used. However, as nothing is actually being cast (it is an unevaluated context), the c-style cast does not do much harm. Note how by using the cast to void the user defined operator, is bypassed and the correct return type is deduced: https://godbolt.org/z/jozx1YGWr. This is because void, whatever uses the built-in operator, whose result is of same type as whatever. You cannot override void, whatever with a user-defined operator,; there is no syntax that works.
I suppose the code is merely to illustrate this one effect, because even with the cast to void one can make up other examples that fail (eg the template does not explicitly test for t.size() actually returning T::size_type).
See also the section on "Rarely overloaded operators" here:
The comma operator, operator,. Unlike the built-in version, the overloads do not sequence their left operand before the right one. (until C++17) Because this operator may be overloaded, generic libraries use expressions such as a,void(),b instead of a,b to sequence execution of expressions of user-defined types. The boost library uses operator, in boost.assign, boost.spirit, and other libraries. The database access library SOCI also overloads operator,.
I have a class that has both implicit conversion operator() to intrinsic types and the ability to access by a string index operator[] that is used for a settings store. It compiles and works very well in unit tests on gcc 6.3 & MSVC however the class causes some ambiguity warnings on intellisense and clang which is not acceptable for use.
Super slimmed down version:
https://onlinegdb.com/rJ-q7svG8
#include <memory>
#include <unordered_map>
#include <string>
struct Setting
{
int data; // this in reality is a Variant of intrinsic types + std::string
std::unordered_map<std::string, std::shared_ptr<Setting>> children;
template<typename T>
operator T()
{
return data;
}
template<typename T>
Setting & operator=(T val)
{
data = val;
return *this;
}
Setting & operator[](const std::string key)
{
if(children.count(key))
return *(children[key]);
else
{
children[key] = std::shared_ptr<Setting>(new Setting());
return *(children[key]);
}
}
};
Usage:
Setting data;
data["TestNode"] = 4;
data["TestNode"]["SubValue"] = 55;
int x = data["TestNode"];
int y = data["TestNode"]["SubValue"];
std::cout << x <<std::endl;
std::cout << y;
output:
4
55
Error message is as follows:
more than one operator "[]" matches these operands:
built-in operator "integer[pointer-to-object]" function
"Setting::operator[](std::string key)"
operand types are: Setting [ const char [15] ]
I understand why the error/warning exists as it's from the ability to reverse the indexer on an array with the array itself (which by itself is extremely bizarre syntax but makes logical sense with pointer arithmetic).
char* a = "asdf";
char b = a[5];
char c = 5[a];
b == c
I am not sure how to avoid the error message it's presenting while keeping with what I want to accomplish. (implicit assignment & index by string)
Is that possible?
Note: I cannot use C++ features above 11.
The issue is the user-defined implicit conversion function template.
template<typename T>
operator T()
{
return data;
}
When the compiler considers the expression data["TestNode"], some implicit conversions need to take place. The compiler has two options:
Convert the const char [9] to a const std::string and call Setting &Setting::operator[](const std::string)
Convert the Setting to an int and call const char *operator[](int, const char *)
Both options involve an implicit conversion so the compiler can't decide which one is better. The compiler says that the call is ambiguous.
There a few ways to get around this.
Option 1
Eliminate the implicit conversion from const char [9] to std::string. You can do this by making Setting::operator[] a template that accepts a reference to an array of characters (a reference to a string literal).
template <size_t Size>
Setting &operator[](const char (&key)[Size]);
Option 2
Eliminate the implicit conversion from Setting to int. You can do this by marking the user-defined conversion as explicit.
template <typename T>
explicit operator T() const;
This will require you to update the calling code to use direct initialization instead of copy initialization.
int x{data["TestNode"]};
Option 3
Eliminate the implicit conversion from Setting to int. Another way to do this is by removing the user-defined conversion entirely and using a function.
template <typename T>
T get() const;
Obviously, this will also require you to update the calling code.
int x = data["TestNode"].get<int>();
Some other notes
Some things I noticed about the code is that you didn't mark the user-defined conversion as const. If a member function does not modify the object, you should mark it as const to be able to use that function on a constant object. So put const after the parameter list:
template<typename T>
operator T() const {
return data;
}
Another thing I noticed was this:
std::shared_ptr<Setting>(new Setting())
Here you're mentioning Setting twice and doing two memory allocations when you could be doing one. It is preferable for code cleanliness and performance to do this instead:
std::make_shared<Setting>()
One more thing, I don't know enough about your design to make this decision myself but do you really need to use std::shared_ptr? I don't remember the last time I used std::shared_ptr as std::unique_ptr is much more efficient and seems to be enough in most situations. And really, do you need a pointer at all? Is there any reason for using std::shared_ptr<Setting> or std::unique_ptr<Setting> over Setting? Just something to think about.
I have the following code I'm trying to adapt for my own purposes. This is a learning exercise for me to attempt an update of my C++ skills.
This was originally written with Clang 3.1 in mind as far as I can tell.
I've tried compiling with Clang versions from 3.1 to 4.0 and GCC 4.9 to 7.1 with very similar results.
These are the error messages from GCC 5.1
Error 1: In instantiation of 'constexpr Struct<Fields>::Struct(T&& ...) [with T = {Struct<foo<int>, bar<double> >&}; Fields = {foo<int>, bar<double>}]':
<source>:46:12: required from here
Error 2: <source>:28:61: error: mismatched argument pack lengths while expanding 'Fields'
constexpr Struct(T &&...x) : Fields{static_cast<T&&>(x)}... {}
Please ELI5 if you have the patience :P
You can see this in godbolts compiler doohickey here:
https://godbolt.org/g/2dRPXf
EDIT:
Given the answers by #Passer-By and #Daniel-Jour, I wonder if Struct(Struct const &) = default; is even necessary. Will removing this constructor from Struct have effects of which I am not aware or do no foresee (I am no C++ Swami!)?
Is the constructor constexpr Struct(T &&...x) : Fields{static_cast<T&&>(x)}... {} a good stand-in for what would otherwise be generated by Struct(Struct const &) = default;?
I'm feeling pretty ambiguous about either proposed solution so far.
End EDIT
// From http://duriansoftware.com/joe/Self-aware-struct-like-types-in-C++11.html
// edited a bit to stop the compiler whining about comments in multiline macros
#include <type_traits>
#include <utility>
#define SELFAWARE_IDENTIFIER(NAME) \
template<typename T> \
struct NAME { \
T NAME; /* field name */ \
constexpr static char const *name() { return #NAME; } /* field type */ \
using type = T; /* field value generic accessor */ \
T &value() & { return this->NAME; } \
T const &value() const & { return this->NAME; } \
T &&value() && { return this->NAME; } \
};
template<typename...Fields>
struct Struct : Fields... {
// A convenience alias for subclasses
using struct_type = Struct;
// Preserve default constructors
Struct() = default;
Struct(Struct const &) = default;
// Forwarding elementwise constructor
template<typename...T>
constexpr Struct(T &&...x) : Fields{static_cast<T&&>(x)}... {} // Error 2 here
};
SELFAWARE_IDENTIFIER(foo)
SELFAWARE_IDENTIFIER(bar)
// Aliasing a Struct instance
using FooBar = Struct<foo<int>, bar<double> >;
// Inheriting a Struct instance (requires inheriting constructors)
struct FooBar2 : Struct<foo<int>, bar<double>> { using struct_type::struct_type; };
static_assert(std::is_trivial<FooBar>::value, "should be trivial");
static_assert(FooBar{2, 3.0}.foo + FooBar{2, 4.0}.foo == 4, "2 + 2 == 4");
FooBar frob(int x) {
FooBar f = {x, 0.0};
f.foo += 1;
f.bar += 1.0;
return f; // Error 1 here
}
You've fallen victim of what I know as "too perfect forwarding".
To debug this, first look closely at the error message:
instantiation of constexpr Struct<Fields>::Struct(T&& ...) [with T = {Struct<foo<int>, bar<double> >&}; Fields = {foo<int>, bar<double>}]:
This tells us that this line of code
return f;
does not as expected call the copy or move constructor, but rather the perfect forwarding constructor.
Looking at what this constructor does, it's clear that this constructor is not capable of copying or moving from a Struct. Its intended use case is to construct each of the fields from one of the arguments. But the error message shows that there is only a single argument of type Struct<foo<int>, bar<double> >&. Because the expansion of the arguments also expands Fields (of which there are two) you get that second error:
[..] error: mismatched argument pack lengths [..]
But why does it take the perfect forwarding constructor instead of the also available copy constructor? Because the forwarding constructor is able to provide a better candidate (an exact match actually) than the copy constructor (whose signature is Struct(Struct const &)): Struct(Struct & &&), which according to the reference combination rules is Struct(Struct &). And that's exactly what's needed to use f in return f;: after all f is a non const lvalue.
One possibility to fix this is to provide another (copy) constructor with the exact signature:
Struct(Struct & s)
: Struct(static_cast<Struct const &>(s))
{}
But if you also add in volatile you need to write a total of six constructors to have all cases covered. Not nice.
The better solution is to exclude the perfect forwarding constructor from overload resolution with SFINAE:
template<typename T>
using decay_t = typename decay<T>::type;
template<
typename...T,
std::enable_if<
(sizeof...(T) == sizeof...(Fields))
&& not_self_helper<Struct, std::tuple<decay_t<T>...>>::value
>::type * = nullptr
>
constexpr Struct(T &&...x)
: Fields{static_cast<T&&>(x)}... {}
not_self_helper checks whether a single parameter passed to a structure with a single field is of the structures own type:
template<typename, typename>
struct not_self_helper : std::true_type {};
template<typename Self>
struct not_self_helper<Self, std::tuple<Self>> : std::false_type {};
This fixes your main issue: The forwarding constructor is semantically just wrong. It does not take an arbitrary number of parameters, but needs exactly the same number of parameters as the structure has fields. Further, none of the fields should be constructed from the containing structure itself (recursive membership means infinite structure size, after all). I shortened that test to only check when there's a single argument, though. Strictly speaking, this is semantically wrong, but in practice it covers the most "dangerous" case: When your forwarding constructor is wrongfully selected for copy/move construction.
The problem consists of two parts
Overload resolution
For a variadic constructor with forwarding references
template<typename... Args>
Struct(Args&&...);
Given any lvalue arguments, Args will be deduced as lvalue references, and rvalue arguments rvalue references.
For another constructor to be called, the variadic constrcutor must not have a better conversion sequence than the constructor.
Your code includes only one other constructor that takes one parameter, the copy constructor
Struct(const Struct&);
A lvalue const Struct will bind with the copy constructor's const Struct& while a lvalue or rvalue Struct will bind with the variadic constructor's Struct& or Struct&& respectively.
Value category of returned type
A glvalue expression referring to an automatic duration variable declared in the function in a return statement is considered a xvalue, and would therefore bind to Struct&& first. When that fails, the expression will be considered a lvalue and proceed to bind to Struct& or const Struct&.
In this case, Struct&& succeeds with the variadic constructor, but results in an error.
If a move constructor is provided, the move constructor will be selected after overload resolution discards the variadic constructor.
Responding to edit
Removing your user-provided copy constructor will allow for an implicitly declared move constructor, which will make the code compile, following the reasons above.
The variadic constructor is not a good stand in for either constructors, aside from being semantically wrong, it takes arbitrary arguments but requires a fixed (in this case 2) amount of arguments to initialize the fields. If it were to be used as a copy constructor, you will get the same compile error: mismatched argument pack lengths while expanding 'Fields'
As was mentioned in Daniel Jour's answer, you should probably put some SFINAE in the variadic constructor to alleviate some pain.