假设您有一个std::tuple
和一个函数,它根据类型修改其值。
template<typename T, typename Ts...>
void modify(std::tuple<Ts...>& tuple, const T& value)
{
std::get<T>(tuple) = value;
}
现在假设,你想 log 那些函数调用,即记住元组中值的修改顺序。这是一个简单的机制。
void log(std::size_t index)
{
static std::vector<std::size_t> logged_indexes;
logged_indexes.push_back(index)
}
以下帮助
// counts until T is same as N'th type of Tuple
template<typename Tuple, typename T, std::size_t N>
struct tuple_type_index_impl;
template<typename T, std::size_t N>
struct tuple_type_index_impl<std::tuple<>, T, N>
{
static constexpr std::size_t value = N;
};
template<typename First, typename... Rest, typename T, std::size_t N>
struct tuple_type_index_impl<std::tuple<First, Rest...>, T, N>
{
static constexpr std::size_t value = std::is_same<First, T>::value
? N
: tuple_type_index_impl<std::tuple<Rest...>, T, N + 1>::value;
};
// helper variable
template<typename Tuple, Typename T>
constexpr std::size_t tuple_type_index_v = typename tuple_type_index_impl<Tuple, T, 0>::value;
我们可以有这种用法
template<typename T, typename Ts...>
void modify(std::tuple<Ts...>& tuple, const T& value)
{
std::get<T>(tuple) = value;
log(tuple_type_index_v<std::tuple<Ts...>, T>);
}
哪种方法适用于日志记录。但是假设您必须根据索引再次访问元组。我们可以使用开关将转换运行时索引转换为constexpr
可以编译生成。但它真的是我们能做的最好的吗?在调用日志时, 但这无济于事,因为我们仍然将它传递给矢量。我们可以(?)构建switch (value)
{
case 0: return std::get<0>(tuple);
case 1: return std::get<1>(tuple);
...
}
index
仍然是constexpr,因此我们可以将其移动到模板参数。template<std::size_t index>
void log()
{
static std::vector<std::size_t> logged_indexes;
logged_indexes.push_back(index);
}
std::index_sequence
,但我们最终会用完模板参数。我的一部分认为这不可能做到,但另一方反对,因为index
是constexpr。是否有可能开发某种std::vector<constexpr std::size_t>
?
答案 0 :(得分:1)
将您的switch
转换为&#34;直接&#34;打电话,你可以这样做:
template <typename ... Ts>
void print(const std::tuple<Ts...>& t, std::size_t index)
{
if (sizeof...(Ts) < index) {
throw std::runtime_error("invalid index");
}
using func_t = void (*)(const std::tuple<Ts...>&);
func_t fs[] = { (+[](const std::tuple<Ts...>& t){
std::cout << std::get<Ts>(t) << std::endl;
})...
// gcc dislikes that lambda,
// but you can create template function instead
};
fs[index](t);
}