I have derived from std::tuple
and but was unable construct the derived class from an initializer list due to issues with class template argument deduction. Is there a better way to construct such a class beyond just giving it an already constructed tuple first{ std::tuple{1, 1.0f, 1u} };
.
template <typename T, typename... Types>
struct first : public std::tuple<T, Types...>
{
//using std::tuple<T, Types...>::tuple;
template<typename F>
requires std::invocable<F, T>
auto transform(F f)
{
auto result = *this;
std::get<0>(result) = f(std::get<0>(result));
return result;
}
};
int main()
{
//auto tuple = first{ 1, 1.0f, 1u };
auto tuple = first{ std::tuple{1, 1.0f, 1u} };
auto tuple2 = tuple.transform([](auto a) {return a 3; });
}
CodePudding user response:
I can't exactly tell you why the using std::tuple<T, Types...>::tuple;
directive doesn't work here, but everything seems to work fine, if you simply define the constructors for taking the parameters T, Types...
and for taking a std::tuple<T, Types...>
manually:
template <typename T, typename... Types>
struct first : public std::tuple<T, Types...>
{
first(T&& t, Types&&... vals)
: std::tuple<T, Types...>{t, std::forward<Types>(vals)...}
{}
first(std::tuple<T, Types...>&& t)
: std::tuple<T, Types...>(t)
{}
template<typename F>
requires std::invocable<F, T>
auto transform(F f)
{
auto result = *this;
std::get<0>(result) = f(std::get<0>(result));
return result;
}
};
int main()
{
auto tuple1 = first{1, 1.0f, 1u};
auto tuple2 = first{std::tuple{1, 1.0f, 1u}};
auto tuple3 = tuple2.transform([](auto a) {return a 3; });
std::cout << std::get<0>(tuple1) << ", " << std::get<1>(tuple1) << ", " << std::get<2>(tuple1) << std::endl;
std::cout << std::get<0>(tuple3) << ", " << std::get<1>(tuple3) << ", " << std::get<2>(tuple3) << std::endl;
}
The output is:
1, 1, 1
4, 1, 1
This is what you intended?
CodePudding user response:
Inherited constructors are not part of CTAD.
You might replicate std::tuple's CTAD:
template <typename T, typename... Types>
first(T, Types...) -> first<T, Types...>;
// auto tuple = first{1, 1.0f, 1u}; // is ok now
// auto tuple = first{ std::tuple{1, 1.0f, 1u} }; // broken now