C++ 如何使结构内部的可变模板在外部可访问?
我使用获取lambda函数的类型(返回和参数)。以下是答案中的相关代码:C++ 如何使结构内部的可变模板在外部可访问?,c++,templates,c++14,metaprogramming,variadic-templates,C++,Templates,C++14,Metaprogramming,Variadic Templates,我使用获取lambda函数的类型(返回和参数)。以下是答案中的相关代码: template <typename T> struct function_traits : public function_traits<decltype(&T::operator())> {}; // For generic types, directly use the result of the signature of its 'operator()' template
template <typename T>
struct function_traits
: public function_traits<decltype(&T::operator())>
{};
// For generic types, directly use the result of the signature of its 'operator()'
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
// we specialize for pointers to member function
{
enum { arity = sizeof...(Args) };
// arity is the number of arguments.
typedef ReturnType result_type;
template <size_t i>
struct arg
{
typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
// the i-th argument is equivalent to the i-th tuple element of a tuple
// composed of those arguments.
};
};
模板
结构功能特性
:公共职能
{};
//对于泛型类型,直接使用其“运算符()的签名结果”
模板
结构功能特性
//我们专门提供指向成员函数的指针
{
枚举{arity=sizeof…(Args)};
//arity是参数的数量。
typedef返回类型结果\ u类型;
模板
结构参数
{
typedef typename std::tuple_元素::type type;
//第i个参数相当于元组的第i个元组元素
//由这些论点组成。
};
};
我想创建一个参数列表,自动将lambda转换为函数指针:
template<typename Func>
constexpr auto l2f(Func lambda) {
typedef function_traits<Func> traits;
return static_cast<traits::result_type(*)( ..all the args.. )(lambda);
}
模板
constexpr自动l2f(Func lambda){
类型定义功能特征;
返回static_castAs,并非所有lambda都可以转换为指针,只有那些没有捕获的lambda。对于那些没有捕获的lambda,它们有一个隐式转换,可以通过在前面添加一个+
来强制转换
但要直接回答您的问题,只需在trait中添加签名
template<typename C, typename R, typename... Args>
struct function_traits<R (C::*)(Args...)>
{
using signature = R(Args...);
};
template<typename F>
auto cast(F f)
{
return static_cast<typename function_traits<F>::signature*>(f);
}
模板
结构功能特性
{
使用signature=R(Args…);
};
模板
自动浇铸(F)
{
返回静态_-cast(f);
}
但我真正想知道的是如何使函数中的arg内容可用,以便从外部访问它,以及如何“内联”多个模板,然后展开它们
首先,我想到的最简单的解决方案是定义一个特定的类型作为路人建议的签名
我提出了一个稍微不同的解决方案,但想法是一样的:您可以定义
using func_type = std::function<ReturnType(Args...)>;
对于更一般的问题(“如何使函数中的arg内容可用以从外部访问它,以及如何“内联”多个模板然后展开它们”),我建议避免定义模板arg
struct,而只是在function\u traits
using tuple_type = std::tuple<Args...>;
template <std::size_t I>
using a_type = std::tuple_element_t<I, tuple_type>;
并且helper函数可以写成
template <typename Func, std::size_t ... Is>
constexpr auto l2f_helper (Func lambda,
std::index_sequence<Is...> const &)
{
return static_cast<std::function<
typename function_traits<Func>::result_type(
std::tuple_element_t<Is,
typename function_traits<Func>::tuple_type> ...)>>(lambda);
}
一点改进:如果您还使用函数中的模板定义了以下
using tuple_type = std::tuple<Args...>;
template <std::size_t I>
using a_type = std::tuple_element_t<I, tuple_type>;
模板
使用类型=std::tuple\u元素;
助手函数可以简化如下
template <typename Func, std::size_t ... Is>
constexpr auto l2f_helper (Func lambda,
std::index_sequence<Is...> const &)
{
return static_cast<std::function<
typename function_traits<Func>::result_type(
typename function_traits<Func>::template a_type<Is>...)>>(lambda);
}
模板
constexpr自动l2f_辅助对象(Func lambda,
std::index_序列常量&)
{
返回静态_cast>(λ);
}
您的前提是错误的:并非所有lambda都可以转换为函数指针!而且,那些可以转换的lambda将在需要它的上下文中自动/轻松地转换,或者您可以简单地触发这种衰减,例如使用+
符号:例如:+[]{}
转换为void(*)()
。所以您不需要函数来完成此操作。谢谢,我知道有捕获的lambda不允许转换为函数指针。我尝试了+[]{}
但不起作用,我认为它在MSVC编译器中不起作用,或者我用了错误的方法。我知道我不清楚,但lambda转换更像是真实问题的一个例子。这是我现在面临的问题,但我想知道的是模板的东西,我对模板非常陌生,不知道大多数模板是如何做到的hings工作。这正是我正在搜索的,特别是第二部分,非常感谢max66。事实上,它非常丑陋和复杂。只是出于好奇,你知道是否有可能让std::make_index_序列在相同的函数中给出index_序列?(而不是必须有一个助手函数来接收索引)@DiogoParreira-不是很复杂,但是,是的:非常难看。不是的:我不知道如何从std::make_index_sequence
传递到相应的std::index_sequence
避免使用helper函数。如果你找到了方法,请告诉我:我在找它有好几年了。
#include <tuple>
#include <iostream>
#include <functional>
#include <type_traits>
template <typename T>
struct function_traits
: public function_traits<decltype(&T::operator())>
{ };
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
{
static constexpr std::size_t arity { sizeof...(Args) };
using result_type = ReturnType;
using func_type = std::function<ReturnType(Args...)>;
using tuple_type = std::tuple<Args...>;
};
template <typename Func>
constexpr auto l2f_v1 (Func lambda)
{ return static_cast<typename function_traits<Func>::func_type>(lambda); }
template <typename Func, std::size_t ... Is>
constexpr auto l2f_v2_helper (Func lambda,
std::index_sequence<Is...> const &)
{
return static_cast<std::function<
typename function_traits<Func>::result_type(
std::tuple_element_t<Is,
typename function_traits<Func>::tuple_type> ...)>>(lambda);
}
template <typename Func>
constexpr auto l2f_v2 (Func lambda)
{ return l2f_v2_helper(lambda,
std::make_index_sequence<function_traits<Func>::arity>{}); }
int main ()
{
auto f1 = l2f_v1([](int, long){ std::cout << "lambda1!" << std::endl; });
auto f2 = l2f_v2([](int, long){ std::cout << "lambda2!" << std::endl; });
f1(1, 2L);
f2(2, 3L);
static_assert( std::is_same<decltype(f1), decltype(f2)>{}, "!" );
}
template <std::size_t I>
using a_type = std::tuple_element_t<I, tuple_type>;
template <typename Func, std::size_t ... Is>
constexpr auto l2f_helper (Func lambda,
std::index_sequence<Is...> const &)
{
return static_cast<std::function<
typename function_traits<Func>::result_type(
typename function_traits<Func>::template a_type<Is>...)>>(lambda);
}