C++模板函数指针类型推导

时间:2021-03-26 01:03:11

标签: c++ c++11 templates lambda type-deduction

我有以下代码

using my_map_t = std::map<int, Object<double>>;
using my_map_iterator_t = my_map_t::iterator;


template <typename FWD, typename Func>
void inner(my_map_t& map, int key, FWD&& obj, Func emplacer) {
        emplacer(map, key, std::forward<FWD>(obj));
}
  

my_map_t map;

template <typename FWD>
void outer(my_map_t& map, int key, FWD&& obj)
{
        auto lambda = [](my_map_t& m, int k, FWD&& o) {
                m.emplace(k, std::forward<FWD>(o));
        };

        inner(map, key, std::forward<FWD>(obj), lambda);
}

可以轻松编译。所以这意味着他自动推导出 inner 函数的模板参数。 但是,如果我引入一个函数指针,我需要指定函数指针模板参数,否则编译器会抱怨

using my_map_t = std::map<int, Object<double>>;
using my_map_iterator_t = my_map_t::iterator;


template <typename FWD, typename Func>
void inner(my_map_t& map, int key, FWD&& obj, Func emplacer) {
        emplacer(map, key, std::forward<FWD>(obj));
}

template <typename FWD, typename Func>
void(*fp)(my_map_t&, int, FWD&&, Func) = &inner;


my_map_t map;

template <typename FWD>
void outer(my_map_t& map, int key, FWD&& obj)
{
        auto lambda = [](my_map_t& m, int k, FWD&& o) {
                m.emplace(k, std::forward<FWD>(o));
        };

        (*fp<FWD, decltype(lambda)>)(map, key, std::forward<FWD>(obj), lambda);
}

为什么在函数指针的情况下,参数推导不再起作用? 我做错了什么吗?有没有办法实现更好的语法?

添加注释

我需要使用函数指针,因为我有一些具有 inner 相同签名的函数。让我们称它们为 inner1inner2inner3。它们被一些外部函数调用

void outer(...) {
     if(...) {

         inner1(...)
     } else if (...) {
     
         inner2(...)
     } else {

         inner3(...)
     }
     some_long_task(...)
}

现在在我的例子中,outer 函数被循环调用。 if 中的检查可能很耗时,并且它们独立于 outer 函数的参数。我正在考虑在执行 some_long_task 时,设置一个指向 right 函数 inner1inner2inner3 的函数指针,利用一些 cpu 并行性,这样,新的循环开始,我就不用浪费时间做 if 检查了。

1 个答案:

答案 0 :(得分:3)

template <typename FWD, typename Func>
void(*fp)(my_map_t&, int, FWD&&, Func) = &inner;

不是普通的函数指针。这就是所谓的variable template。当您有一个变量模板时,为了引用特定的实例化,您必须指定模板参数。为了证明这一点,请考虑

template <typename T>
constexpr T pi = T(3.1415926535897932385L);  

您不能只使用 cout << pi,因为我们不知道使用哪个 pi

出现同样的情况
(*fp<FWD, decltype(lambda)>)(map, key, std::forward<FWD>(obj), lambda);

此处 fp 需要 <FWD, decltype(lambda)>,以便编译器可以知道要引用哪个特定的 fp 实例。它甚至在评估函数调用之前就必须这样做,因为它需要根据函数检查参数。

我们不需要指定参数的是像 CTAD 这样的未来,但适用于函数指针变量 temapltes。

相关问题