【问题标题】:Practical C++ Metaprogramming实用 C++ 元编程
【发布时间】:2017-04-13 14:03:07
【问题描述】:

我刚刚阅读了《实用 C++ 元编程》一书,它有以下示例,我无法编译。你能帮我解决这个问题吗?

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) {});
}

我收到一条编译错误消息:“type”不是“make_tuple_of_params”的任何直接或间接基类的成员。由于选择了默认结构,因此 SFINAE 似乎无法按预期工作。我该如何解决这个问题?

【问题讨论】:

  • lambda 类型不是函数类型。
  • 请记住,c++14 中的 lambda 可以具有 auto 参数,这些参数显然可以被视为模板仿函数。对于这种 lambda,您希望您的元组类型看起来像什么?
  • 上面没有SFINAE,只是特化模板模式匹配

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


【解决方案1】:

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

至于如何解决这个问题:我认为没有一个完全通用的解决方案。对于特定的some_magic_function,可能有一个解决方案/解决方法,但这取决于您需要该功能做什么。

【讨论】:

  • 关于可能的修复:如果不需要捕获任何内容,则可以选择使用 +[] (int, double, float) {} 将 lambda 转换为函数指针。当然make_tuple_of_params此时必须匹配函数指针和函数类型。
  • @0xBADF00 这在 Markus 评论的第二句话中有所提及。
【解决方案2】:

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

#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]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-07
    • 1970-01-01
    • 2010-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多