简体   繁体   中英

std::make_tuple with the input of a manipulated std::tuple unsing concepts in c++20

Kindly considere the following godbolted code written for c++20:

#include<iostream>
#include<tuple>

template <typename T, std::size_t ...I, typename F>
void tuple_foreach_impl(T&& tuple, std::index_sequence<I...>, F&& func)
{
    using dummy_array = int[];
    dummy_array{(void(func(std::get<I>(tuple))), 0)..., 0};
}

template <typename T, typename F>
void tuple_foreach(T&& tuple, F&& func)
{
    constexpr int size = std::tuple_size<std::remove_reference_t<T>>::value;
    tuple_foreach_impl(std::forward<T>(tuple), std::make_index_sequence<size>{},
        std::forward<F>(func));
}

template<typename T>
concept IsOfTypeInt = std::same_as<T, int>;

template<typename T>
concept IsNotOfTypeInt = not IsOfTypeInt<T>;

template<IsOfTypeInt T>
int* ToPtrIfInt(T& arg) { return &arg;}

template<IsNotOfTypeInt T>
T& ToPtrIfInt(T& arg) { return arg;}

template <typename... T, std::size_t... I>
auto ConvertTupleImp(const std::tuple<T...>& t, std::index_sequence<I...>)
{
    return std::make_tuple(ToPtrIfInt(std::get<I>(t))...);
}

int main()
{
    auto t1 = std::make_tuple(1.1,3.14159,42);
    auto t2 = ConvertTupleImp(t1, std::make_index_sequence<3>());

    tuple_foreach(t2, [](auto&& value)
    {
        std::cout << value << std::endl;
    });
}

The output reads:

Program returned: 0
1.1
3.14159
42

The purpose of the function ToPtrIfInt is to return a pointer to the input int if the input is of type int . In any other case ToPtrIfInt should return the input object. As you can see in the output the last element (value 42) is not converted to its pointer. So the code does not work. My guess ist hat I have to use ToPtrIfInt(std::forward<…>(std::get<I>(t)))... But I am not able to get it to work. Any help is appreciated.

You have a constness issue: your tuple is const, so you pass const int& and const int is not a int . removing const solve your issue:

template <typename... Ts, std::size_t... Is>
auto ConvertTupleImp(std::tuple<Ts...>& t, std::index_sequence<Is...>)
{
    return std::make_tuple(ToPtrIfInt(std::get<Is>(t))...);
}

Demo

Alternatively, you might change your concept to handle const (and reference)

template<typename T>
concept IsOfTypeInt = std::same_as<std::decay_t<T>, int>;

You have to fix implementation of ToPtrIfInt to have correct return too.

Demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM