while # 3 should not be allowed because this syntax prevents conversions (at least not for int if you tried to use int {2.1}).
This is not entirely correct. The rule is that narrowing conversions is prohibited. Other conversion types allowed. int{2.1} is a narrowing transformation because it changes the value, losing accuracy. int{2.0} not a narrowing conversion because the value does not change.
The reason # 2 is not that it requires two implicit user conversions, which is prohibited.
Conceptually, copy initialization, such as:
Atreturn hook = []() {};
is equivalent to:
Atreturn hook = Atreturn([]() {});
(except that it cannot call "explicit" constructors, and the compiler is allowed to copy the copy).
This means that first the lambda would have to implicitly convert to function<void()> , and then that would have to implicitly convert to Atreturn . Both of these transformations are a βuser-defined transform sequenceβ, meaning that they invoke the constructor instead of built-in transforms such as int - long , and the standard states that an implicit transform sequence cannot contain more than one user-defined transform.
The problem is actually not related to lambdas, you can demonstrate exactly the same error as this:
struct L { }; struct F { F(L) { } }; struct A { A(F) { } }; A a = L(); l.cc:4:9: error: conversion from 'L' to non-scalar type 'A' requested A a = L(); ^
Again, the problem is that the implicit conversion sequence L -> F -> A includes two user conversions that are forbidden.
I donβt have much sympathy for your problem related to the need to adapt the code to help indent automatically - the code should not be distorted so that it distorts the editor. However, another option is to add a template constructor that accepts anything that can be converted to std::function<void()> for example.
struct Atreturn { using func_type = std::function<void()>; template<typename T, typename Requires = decltype(func_type(std::declval<T&&>())> Atreturn(T t) : funcdestr(std::move(t)) { } ... };
This will convert the lambda directly to Atreturn , without first requiring an implicit conversion to function<void()> .