C++ Logo

std-proposals

Advanced search

Re: [std-proposals] C++ feature ideea/proposal

From: Gašper Ažman <gasper.azman_at_[hidden]>
Date: Tue, 5 Apr 2022 13:14:53 +0100
https://godbolt.org/z/fdh3hcWjc

^^ library implementation of `ambiguous` that causes exactly one line of
overhead and gives you curried return type deduction.

Code also below. If you don't understand how this works, I'm sure someone
will be glad to explain - but this is how I'd do exactly what you wanted,
in library.

#include <type_traits>
#include <concepts>
#include <utility>
#include <string>
#include <sstream>
#include <tuple>

template <typename F_, typename... Ts_>
struct cvt_adaptor {
F_ f;
std::tuple<Ts_...> args;

template <typename T_>
requires(requires (Ts_... ts) {
{ std::move(f)(std::type_identity<T_>{}, ts...) } ->
std::convertible_to<T_>;
})
constexpr operator T_ () &&
noexcept(noexcept(std::move(f)(std::type_identity<T_>{},
std::declval<Ts_>()...))) {
return [&]<std::size_t... is>(std::index_sequence<is...>){
return std::move(f)(std::type_identity<T_>{},
std::get<is>(std::move(args))...);
}(std::index_sequence_for<Ts_...>{});
}
};

template <typename... Fs_>
struct overload : Fs_... {
using Fs_::operator()...;
};

template <typename T_, typename... Xs_>
concept one_of = (... || std::is_same_v<T_, std::type_identity<Xs_>>);

// --- ^^^ --- write onece, in your library somewhere
// --- vvv ---- your ambiguous function

constexpr auto ambiguous(std::string s) {
return cvt_adaptor{overload{
[](one_of<std::string> auto return_type, auto&& s) {
return std::move(s);
},
[](one_of<int, float, double> auto return_type, auto&& s) {
std::stringstream ss(std::move(s));
typename decltype(return_type)::type x;
ss >> x;
return x;
}
}, std::tuple{std::move(s)}};
}

int main() {
float a = ambiguous("5.2");
int i = ambiguous("5");
// traits work too
static_assert(!std::is_convertible_v<std::size_t, decltype(ambiguous("3"
))>);
}

On Tue, Apr 5, 2022 at 12:23 PM PaulIRL via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> I understand and I agree, this is a much better way of doing things
> because with my way there wouldn't been too many changes for only a few
> reasons, thanks!
>
> Trimis cu ProtonMail <https://protonmail.com/> e-mail securizat.
>
> ------- Original Message -------
> Garrett May via Std-Proposals <std-proposals_at_[hidden]> - marți, 5
> aprilie 2022 la 2:19 PM a scris:
>
> You can do the following with concepts in C++20:
>
> #include <concepts>
> #include <iostream>
>
> template<std::same_as<int> T>
> T RandomNumber(){
> return 7; // for simplicity
> }
>
> template<std::same_as<float> T>
> T RandomNumber(){
> return 5.2; // for simplicity again
> }
>
> int main(){
> std::cout << RandomNumber<int>() << std::endl;
> std::cout << RandomNumber<float>() << std::endl;
> return 0;
> }
>
> which enforces a requirement on the template function.
>
> The problem with casting is that RandomNumber() would have to deducible
> in the first place, which it isn't as you don't know the return type ahead
> of time. For example:
>
> auto result = RandomNumber();
>
> What would the type of result be? In other languages (like Rust), this
> detail can be omitted until very late; but in C++, adding this could be
> quite difficult.
> If the aim is to simply be able to do (T)RandomNumber(), then I don't see
> any advantage doing that over doing it via RandomNumber<T>() instead.
>
> On Tue, 5 Apr 2022 at 12:00, Gašper Ažman via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> You can emulate that by returning a type with two conversion operators to
>> the types you want.
>>
>> On Tue, Apr 5, 2022 at 11:59 AM PaulIRL via Std-Proposals <
>> std-proposals_at_[hidden]> wrote:
>>
>>> Hi, I'm currently learning C++ and at first I wondered why we can have 2
>>> functions with the same name and different parameters but, not with the
>>> same name, same parameters and a different return type, but probably this
>>> is because the c++ compiler wouldn't know which function to call, however,
>>> I think that a good solution is forcing the user (programmer) to cast the
>>> output, and that way the compiler will know which function to call.
>>> Example
>>> int RandomNumber() {
>>> return 7; //for simplicity
>>> }
>>>
>>> float RandomNumber() {
>>> return 5.2 //for simplicity again
>>> }
>>>
>>> one could do
>>>
>>> std::cout<<(float)RandomNumber()<<std::endl; //prints 5.2\n
>>>
>>> however
>>> std::cout<<RandomNumber()<<std::endl;
>>> would throw a compiler error
>>>
>>> this would also work as expected
>>> std::cout<<(int)(float)RandomNumber()<<std::endl; //prints 5\n
>>>
>>> - Paul Abrudan
>>>
>>> Trimis cu ProtonMail <https://protonmail.com/> e-mail securizat.
>>> --
>>> Std-Proposals mailing list
>>> Std-Proposals_at_[hidden]
>>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>>
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2022-04-05 12:15:06