依赖于规则的模板成员变量
Template member variables depending on rules
在以下代码中:
#include <iostream>
#include <tuple>
template<typename T>
struct Container
{
std::string id;
T value;
Container(std::string id, T value) : id(id), value(value) {}
};
template<typename... T>
struct ElementCodec
{
std::tuple<T...> values;
ElementCodec(T... args) : values(args...) {}
};
template<typename... T> ElementCodec(T...) -> ElementCodec<T...>;
int main()
{
ElementCodec a { int { 5 }, double { 3. }, Container { "52", 7 } };
auto [x, y, container] = a.values;
std::cout << x << ", " << y << ", " << container.value << '\n';
}
在给定代码特化后,元组 values
的类型为 std::tuple<int, double, Container<int>>
。我想做的是将其衰减为存储在容器中的类型,因此 std::tuple<int, double, int>
无需通过 container.value
进行访问。
这可以在 c++17 中实现吗?我已经在这个问题上停留了一段时间了,但真的找不到任何关于这个的资源。
您可以使用辅助函数解开 Container<T>
s:
template <typename T> T unwrap(T value) { return value; }
template <typename T> T unwrap(Container<T> c) { return c.value; }
template <typename T> using unwrap_t = decltype(unwrap(std::declval<T>()));
然后相应地调整您的模板和推导指南:
template <typename... T>
struct ElementCodec
{
std::tuple<T...> values;
template <typename... Us>
ElementCodec(Us... args) : values(unwrap(args)...) {}
};
template<typename... T>
ElementCodec(T...) -> ElementCodec<unwrap_t<T>...>;
以上不适用于 gcc(参见 ),您可以使用约束修复它:
template <typename... Us,
std::enable_if_t<std::is_constructible_v<
std::tuple<T...>, unwrap_t<Us>...
>, int> = 0>
ElementCodec(Us... args) : values(unwrap(args)...) {}
在以下代码中:
#include <iostream>
#include <tuple>
template<typename T>
struct Container
{
std::string id;
T value;
Container(std::string id, T value) : id(id), value(value) {}
};
template<typename... T>
struct ElementCodec
{
std::tuple<T...> values;
ElementCodec(T... args) : values(args...) {}
};
template<typename... T> ElementCodec(T...) -> ElementCodec<T...>;
int main()
{
ElementCodec a { int { 5 }, double { 3. }, Container { "52", 7 } };
auto [x, y, container] = a.values;
std::cout << x << ", " << y << ", " << container.value << '\n';
}
在给定代码特化后,元组 values
的类型为 std::tuple<int, double, Container<int>>
。我想做的是将其衰减为存储在容器中的类型,因此 std::tuple<int, double, int>
无需通过 container.value
进行访问。
这可以在 c++17 中实现吗?我已经在这个问题上停留了一段时间了,但真的找不到任何关于这个的资源。
您可以使用辅助函数解开 Container<T>
s:
template <typename T> T unwrap(T value) { return value; }
template <typename T> T unwrap(Container<T> c) { return c.value; }
template <typename T> using unwrap_t = decltype(unwrap(std::declval<T>()));
然后相应地调整您的模板和推导指南:
template <typename... T>
struct ElementCodec
{
std::tuple<T...> values;
template <typename... Us>
ElementCodec(Us... args) : values(unwrap(args)...) {}
};
template<typename... T>
ElementCodec(T...) -> ElementCodec<unwrap_t<T>...>;
以上不适用于 gcc(参见
template <typename... Us,
std::enable_if_t<std::is_constructible_v<
std::tuple<T...>, unwrap_t<Us>...
>, int> = 0>
ElementCodec(Us... args) : values(unwrap(args)...) {}