Comments (5)
It is temporarily by design. You may note that std::move_only_function
supports no CTAD (other than moving itself). The reasons are
move_only_function
is meant to erase type from multiple objects. Therefore, it should declare a type; otherwise, we're reducing all callable objects to a type similar to the first one that initializes the wrapper.- The top 3 places where type-erased callable wrappers appear are members, the value of key-value pairs in a container, and parameters. You cannot use CTAD in any of those.
- Unlike
std::function
,move_only_function
can be ref-qualified,const
-qualified,noexcept
-qualified. It is unclear how CTAD would handle these. The design in my mind is thatnoexcept
should be reflected in the deduced call signature; others should not. But as noted by Arthur O'Dwyer and myself, the trouble is that if two callables differ only innoexcept
deduce to different erased-type, assigning one to the other will create a wrapper on top of the wrapper. It is worse infunction_ref
since there can be a dangling wrapper on top of a wrapper.
These issues apply to std::function_ref
as well, plus that function_ref
has the potential of introducing dangling reference in an initializing declaration -- unless the right-hand side is a function (pointer).
In contrast, the CTAD on std::function
was somewhat experimental. It's not harmful because std::function
is immune from 3), though.
My feeling is that, CTAD on function_ref
(and move_only_function
) need motivation. I want to see some context and motivating examples; the consistency argument (i.e., to be consistent with std::function
) doesn't apply here.
from nontype_functional.
Thanks for the explanation.
Some context & motivation: I noticed that quite often I try to write
auto handler1 = [&](){};
auto handler2 = [&](){};
auto handler = condition?
handler1 :
handler2;
// Call handler more than once
This obviously does not work, because handler1
and handler2
are unrelated and have no common type.
Type-erasing them with std::function
helps:
auto handler = condition?
std::function(handler1) :
std::function(handler2);
but obviously has an extra cost.
function_ref
feels like a drop-in replacement (and improvement) in this context, but without CTAD it is more verbose (especially with complex signatures):
auto handler = condition?
std23::function_ref<void()>(handler1) :
std23::function_ref<void()>(handler2);
from nontype_functional.
If it is okay to spell the type once, maybe
auto handler = [&] -> std23::function_ref<void()> {
if (cond)
return handler1;
else
return handler2;
}();
https://godbolt.org/z/3r5Pqsdnr
If you definitely want some form of deduction, a weird trick is
auto handler =
cond ? std23::function_ref(
std23::nontype<&decltype(handler1)::operator()>, handler1)
: std23::function_ref(
std23::nontype<&decltype(handler2)::operator()>, handler2);
https://godbolt.org/z/bxhv45q4h
The trick can be an approach if you ditch operator()
altogether. You can write
struct Handler1 {
void fn() {}
} handler1;
struct Handler2 {
void fn() {}
} handler2;
auto handler =
cond ? std23::function_ref(std23::nontype<&Handler1::fn>, handler1)
: std23::function_ref(std23::nontype<&Handler2::fn>, handler2);
https://godbolt.org/z/EsenY6jaK
from nontype_functional.
There are ways of course, but my goal was to reduce the typing and repeating myself, not to get some form of deduction just for the sake of it :)
The design in my mind is that
noexcept
should be reflected in the deduced call signature; others should not
Should it though? noexcept
selling points are optimization opportunities and the contract, important in certain contexts, e.g. move ctors & operators. In case of function_ref
optimizations are probably limited by the indirection anyway and I cannot immediately think of a good example where the noexcept
-ness of it would affect the logic (except the infamous noexcept(noexcept(%the_whole_function_body%))
). However, I am not an expert in this area.
the trouble is that if two callables differ only in
noexcept
deduce to different erased-type, assigning one to the other will create a wrapper on top of the wrapper
CTAD, just like auto
, could deduce something completely different from the user's expectations in certain corner cases and cause troubles. However, I do not think it should be ditched completely because of that: as everything else, it is a tool that could make our lives easier in simple scenarios, should be used responsibly in complex ones and could always be ignored in favor of a more explicit way in case of any uncertainties.
from nontype_functional.
I can argue for noexcept
, others can argue for const
. Since our expectations are diverse, maybe the best approach is to have some traits that are used to fill signature types for all callable types. Like
static_assert(std::is_same_v<common_signature_t<std::function_ref, decltype(handler1), decltype(handler2)>,
std::function_ref<void()>);
and there can be common_signature_const_t
, common_signature_nothrow_t
, etc.
from nontype_functional.
Related Issues (3)
- Please add a license HOT 1
- Clang Support HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from nontype_functional.