【问题标题】:What's the least verbose way to hint a overloaded function template as template parameter提示重载函数模板作为模板参数的最简洁的方法是什么
【发布时间】:2021-03-14 12:06:41
【问题描述】:

我正在尝试创建一个函数模板,它接受 std::max 和其他具有兼容原型的模板:

template <typename F>
int f(F g)
{
    return g(1,2);
}

由于许多重载,模板参数 F 无法推断为 f.e.对于std::max,所以这将失败:

f(std::max);

一种可能性是用static_cast 提示:

f(static_cast<int const& (*)(int const&,int const&)>(std::max));

我正在寻找一种不那么冗长的方式,同时仍然能够轻松传递任何其他类型的匹配函数,例如 f.e.

f([](int i, int j) { return 3; });
f(std::function<int(int,int)>([](int i, int j) { return 4; }));

Here's a godbolt.

如果 C++11 和 C++14 有一个简单的方法,那就太好了,但如果只有一个 C++17 及以上版本,这也会有很大帮助。

【问题讨论】:

  • 按原样传递 lambda?如f([](int a, int b) { return std::max(a, b); })?
  • stackoverflow.com/a/25875538/817643 如果您发现自己经常这样做。请注意,它不涉及noexcept-ness。这需要在宏中进行更多重复。
  • 抱歉吹毛求疵,但表现力是可取的。我想你的意思是冗长、啰嗦、笨拙
  • @largest_prime_is_463035818 无需抱歉;你完全正确。我编辑了那个。

标签: c++ template-argument-deduction function-templates


【解决方案1】:

问题是 std::max 不是你的职能。

您无法修改函数以使其接受一组重载。一组重载不是您可以传递的。您可以传递的是带有重载operator() 的对象。例如

struct foo {
    template <typename T> bool operator()(T a,T b){return a+b;}
};

f(foo{}); // OK 

std::max 但是是一个函数模板,您需要先实例化该函数,然后才能将函数传递给f。你对此无能为力。尽管您不一定需要std::functionstatic_cast 来选择正确的重载。如评论中所述,您可以这样做

 f([](int a, int b) { return std::max(a, b); });

这会在 lambda 中触发 std::max&lt;int&gt; 的实例化,或者如果您更喜欢在 f 中选择类型,您可以像上面的示例一样执行:

 f([](auto a, auto b) { return std::max(a,b); });

这个 lambda 表达式类似于上面的foo。你有一个具体的对象,只有 operator() 是一个模板,它只在调用时被实例化,这样在 f 你甚至可以这样做:

template <typename F>
int f(F g)
{
    if (some_condition) return g(1,2); // calls std::max<int>
    else return g(1.2,1.4);            // calls std::max<double>
                                       // (though int is returned anyhow)
}

f([](auto a, auto b) { return std::max(a,b); });

【讨论】:

  • 我不想承认,但我真的不喜欢 lambda 为未优化的构建引入的开销;见godbolt.org/z/81YcvW
  • @jesses 很好,我喜欢它可以在非调试构建的godbolt.org/z/fG811x 中完全优化掉。为什么要关心调试构建中的开销?
  • 我大致测量了 2 倍;当被调用数十亿次时,这对我正在使用的代码库会变得很重要。
  • @jesse 好的,但你为什么关心非优化构建的性能?
  • @jesses 好的,在这种情况下,我会选择静态演员;)
猜你喜欢
  • 2013-04-15
  • 1970-01-01
  • 2019-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多