简体   繁体   English

实用的C ++元编程

[英]Practical C++ Metaprogramming

I just read the book "Practical C++ Metaprogramming" and it has the following example that I cannot compile. 我刚读过“Practical C ++ Metaprogramming”这本书,它有以下我无法编译的例子。 Can you help sort this out for me. 你能帮忙解决这个问题。

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

I get a compilation error saying: 'type' is not a member of any direct or indirect base class of 'make_tuple_of_params'. 我收到一个编译错误说:'type'不是'make_tuple_of_params'的任何直接或间接基类的成员。 It seams like the SFINAE does not work as expected since the default struct is selected. 由于选择了默认结构,因此SFINAE无法按预期工作。 How do I fix this? 我该如何解决?

The type of [] (int, double, float) {} is an unnamed class type local to main , called the closure type. [] (int, double, float) {}类型是main本地未命名类类型,称为闭包类型。 It is most definitely not void (int, double, float) ; 绝对不是 void (int, double, float) ; it is in fact not a function type at all. 事实上它根本不是一种功能类型。 Therefore, the specialisation for function types doesn't apply, and the primary template is selected. 因此,函数类型的特化不适用,并且选择了主模板。 (Note that no SFINAE is involved in your code). (请注意,您的代码中不涉及SFINAE)。

As for how to fix this: I don't think there's a fully general solution. 至于如何解决这个问题:我认为没有一个完全通用的解决方案。 There could be a solution/workaround for a particular some_magic_function , but that would depend on what you need that function to do. 特定的some_magic_function可能有解决方案/解决方法,但这取决于您需要该功能做什么。

For lambdas if not including lambdas with auto parameters the workaround could look as follows: 对于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] [现场演示]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM