实用的C ++元编程

时间:2016-11-29 14:21:08

标签: c++ c++14 variadic-templates template-meta-programming

我刚读过这本书" Practical C ++ Metaprogramming"它有以下我无法编译的例子。你能帮忙解决这个问题。

template <typename F>
struct make_tuple_of_params;

template <typename Ret, typename... Args>
struct make_tuple_of_params<Ret (Args...)>
{
   using type = std::tuple<Args...>;
};

template <typename F>
using make_tuple_of_params_t = typename make_tuple_of_params<F>::type;

template<typename F>
void some_magic_function(F callable)
{
   make_tuple_of_params_t<F> tuple;
   /*
    ... do something with arguments in tuple...
   */
}

int main()
{
   some_magic_function([] (int, double, float) {});
}

我收到编译错误说:&#39;输入&#39;不属于&#39; make_tuple_of_params&#39;的任何直接或间接基类的成员。由于选择了默认结构,因此SFINAE无法按预期工作。我该如何解决这个问题?

2 个答案:

答案 0 :(得分:6)

[] (int, double, float) {}的类型是main本地的未命名类类型,称为闭包类型。绝对是 {{ 1}};事实上它根本不是一种功能类型。因此,函数类型的特化不适用,并且选择了主模板。 (请注意,您的代码中不涉及SFINAE。)

至于如何解决这个问题:我认为没有一个完全通用的解决方案。对于特定的void (int, double, float),可能存在解决方案/解决方法,但这取决于您需要该功能执行的操作。

答案 1 :(得分:5)

对于lambdas,如果不包括带有自动参数的lambda,则解决方法可能如下所示:

#include <tuple>
#include <typeinfo>
#include <iostream>

template <class>
struct make_tuple_of_params;

template <class Res, class Type, class... Args>
struct make_tuple_of_params<Res (Type::*)(Args...) const> {
    using type = std::tuple<Args...>;
};

template <class F>
using make_tuple_of_params_t = typename make_tuple_of_params<F>::type;

template<typename F>
void some_magic_function(F callable)
{
   make_tuple_of_params_t<decltype(&F::operator())> tuple;
   std::cout << typeid(tuple).name() << std::endl;
}

int main()
{
   some_magic_function([] (int, double, float) {});
}

[live demo]