<gonidelis[m]>
ok first of all sorry for asking over and over again the same question I just want to be sure that I doing this the proper way. I am trying to match the `copy` definitions here to the definitions in std. Ahhh... sorry for the wrong permalink. I meant http://eel.is/c++draft/alg.copy#5
<gonidelis[m]>
hkaiser:
<gonidelis[m]>
I mean the definition under "5"
<hkaiser>
yes, the standard specifies 4 overloads for copy
<gonidelis[m]>
(it' s pretty bad that the definiots are not enumerated btw)
<hkaiser>
two in namespace std, and two in std::ranges
<hkaiser>
we add two overloads in hpx::ranges taking the execution policy
<gonidelis[m]>
the return type is `constexpr OutputIterator`. So I just return sth like `FwdIter2` and the hpx counterpart for `constexpr` ?
<hkaiser>
doubt we can make our algorithms constexpr at this point
<gonidelis[m]>
So I just return fwditer2?
<hkaiser>
also, 'OutputIterator' is just a name, you can use whatever you like
<gonidelis[m]>
yeah yeah... as I said we write it like `fwditer1` `fwditer2`
<gonidelis[m]>
or `typename util::detail::algorithm_result<FwdIter2>` maybe???
<hkaiser>
depends on which algorithm overload you're talking about
<gonidelis[m]>
the non-ranges one
<gonidelis[m]>
ones*
weilewei has quit [Remote host closed the connection]
<hkaiser>
ok, the one with policies or the one without?
<gonidelis[m]>
without
<hkaiser>
then it's just FwdIter2
<hkaiser>
(for copy)
<hkaiser>
for for_each it's probably something else, like F
<gonidelis[m]>
ok I am working on `transform` btw....
<gonidelis[m]>
why do we use the `friend` keyword in front of the return type?
<hkaiser>
read p1895
<gonidelis[m]>
hkaiser: ohh ok... thnx ;)
weilewei has joined #ste||ar
<K-ballo>
they are not just names, they carry requirements with them.. OutputIterator requires an output iterator, FwdIter requires a forward iterator
kale[m] has quit [Ping timeout: 260 seconds]
kale[m] has joined #ste||ar
bita_ has quit [Ping timeout: 260 seconds]
<hkaiser>
K-ballo: in c++20, yes, before that it's just names
<K-ballo>
no, the template param names from [algorithms] have semantic requirements attached
<hkaiser>
ok
<hkaiser>
but not enforced
<K-ballo>
define enforced?
<K-ballo>
they are implicit Requires:
<hkaiser>
compiler enforced
<hkaiser>
yes, I understand
<K-ballo>
that's implementation QoI
kale[m] has quit [Ping timeout: 264 seconds]
kale[m] has joined #ste||ar
<gnikunj[m]>
hkaiser: yt?
<gnikunj[m]>
hkaiser: I had a question about having multiple destructors in C++20
<gnikunj[m]>
my question being, you said SFINAE is bad and we shouldn't use it, but it seems that they're using concepts to get multiple destructors working
<gnikunj[m]>
K-ballo: ^^
<K-ballo>
who said sfinae is bad?
<gnikunj[m]>
I've always had this notion
<gnikunj[m]>
and hartmut usually asks me to not have sfinae in the code
<K-ballo>
sfinae isn't bad, concepts is nothing but sfinae and in itself it's not bad
<gnikunj[m]>
that's why I was a bit wary when I got to know about this feature. What is it that I'm missing?
<K-ballo>
having gratuituos sfinae in code, that's bad
<gnikunj[m]>
how do you know if sfinae was not required?
<K-ballo>
you'd know, it's a fundamental property of the design
<K-ballo>
or are you asking when would you choose to design something to sfinae?
<gnikunj[m]>
I'm asking when do I decide if I want to design it with sfinae
<K-ballo>
so, you begin with a constraint which is a precondition for your function, for instance is_iterator<X>
<K-ballo>
and then you ask if when calling fun(x) with a non-iterator X it's important for your overload to disappear so that a different fun overload may take over
<K-ballo>
take the algorithms for instance, since you are already familiar with them..
<K-ballo>
an is_iterator requirement may make sense, someone else may come up with a similar minded algorithm to operate on non iterators
<gnikunj[m]>
hkaiser told that the compilers handle functions in a single pass and structs in two passes (given a compiler is a 2 pass one) so ordering in sfinae is important. Isn't that a bad thing?
<K-ballo>
however, if the requirement is say bidirectional_iterator, then that's because your algorithm can't reasonably be implemented with iterators less than bidirectional
<K-ballo>
so you may want to sfinae on non-iterators, but not sfinae and fail hard on iterators that aren't bidirectional
<K-ballo>
a similar reason for sfinae is when someone may have a legitimate use case to ask programmatically whether some function is viable or not
<gnikunj[m]>
ok it is starting to make more sense. What is the difference between having a template specialization vs sfinae in that case? I think a sfinae implementation can handled using template specialization as well
<gnikunj[m]>
s/can handled/can be handled
<K-ballo>
in which case?
diehlpk has joined #ste||ar
diehlpk has quit [Changing host]
diehlpk has joined #ste||ar
<gnikunj[m]>
like have a base struct and then multiple variations of it that inherits from the base struct and have partial template specialization of some sort?
<K-ballo>
I can't picture it
<gnikunj[m]>
ok let me put up an example real quick
<K-ballo>
if specializations can actually do the job then they would be prefered to gratuituos sfinae
<K-ballo>
sometimes specializations need to be sfinae driven though, and that's fine too
<gnikunj[m]>
using if constexpr we limit the if statement check at compile time, right?
<K-ballo>
yes.. and it can handle the same kind of scenarios tag dispatching can
<gnikunj[m]>
right
<K-ballo>
(it was designed specifically as a replacement for tag dispatching)
<gnikunj[m]>
essentially make a single function that does the tag dispatching using if constexpr
<K-ballo>
yes
<gnikunj[m]>
wow, nice! I had an incorrect notion of if constexpr in that case. I used to think that it is meant only for optimizing constant if evaluations at compile time (which is essentially the code you shared but I never thought of using it in that way)
<K-ballo>
constant if evaluations are already optimized at compile time without constexpr
<K-ballo>
there are some subtle differences in semantics to a regular if, which makes each branch work as if it were a separate function body
<gnikunj[m]>
got it
diehlpk has quit [Ping timeout: 260 seconds]
<gnikunj[m]>
hkaiser: do have have a cluster with 20 or more nodes per processor type? rostam has a maximum of 16