gpt4 book ai didi

c++ - 初始化列表奇怪地取决于参数的顺序?

转载 作者:行者123 更新时间:2023-11-30 03:40:35 25 4
gpt4 key购买 nike

我有以下代码片段:

#include <type_traits>
#include <limits>
#include <initializer_list>
#include <cassert>

template <typename F, typename... FIn>
auto min_on(F f, const FIn&... v) -> typename std::common_type<FIn...>::type
{
using rettype = typename std::common_type<FIn...>::type;
rettype result = std::numeric_limits<rettype>::max();
(void)std::initializer_list<int>{((f(v) < result) ? (result = static_cast<rettype>(v), 0) : 0)...};
return result;
}

int main()
{
auto mod2 = [](int a)
{
return a % 2;
};

assert(min_on(mod2, 2) == 2); // PASSES as it should
assert(min_on(mod2, 3) == 3); // PASSES as it should
assert(min_on(mod2, 2, 3) == 3); // PASSES but shouldn't - should be 2
assert(min_on(mod2, 2, 3) == 2); // FAILS but shouldn't - should be 2
}

模板函数 min_on 背后的想法是它应该从传递给它的参数列表中返回参数 x v 以便它给出表达式 f(v) 的最小值。

我观察到的问题是 std::initializer_list 中的参数顺序不知何故很重要,所以上面的代码将失败,而这段代码:

  assert(min_on(mod2, 3, 2) == 2);

会起作用。这里可能有什么问题?

最佳答案

你的函数集 resultv如果f(v) < result .与 mod2作为f , f(v)只会导致 0、1 或 -1。这意味着如果你所有的值都大于 1,result将被设置为最后一个 v经过测试,因为f(v)永远小于 result .试着把一个负数放在一堆正数的中间,不管你把它放在哪里,结果总是负数。

assert(min_on(mod2, 2, 3, 4, -3, 7, 6, 5) == -3);

也许你想要这个:

std::initializer_list<int>{((f(v) < f(result)) ? (result = static_cast<rettype>(v), 0) : 0)...};

区别在于我正在测试 f(v) < f(result) , 而不是 f(v) < result .虽然,该函数通常仍然不正确,因为它假定 f(std::numeric_limits<rettype>::max())是最大可能值。在mod2的情况下有用。但是像这样:

[](int a) { return -a; }

这显然是错误的。所以也许你可以改为需要第一个参数:

template <typename F, typename FirstT, typename... FIn>
auto min_on(F f, const FirstT& first, const FIn&... v)
-> typename std::common_type<FirstT, FIn...>::type
{
using rettype = typename std::common_type<FirstT, FIn...>::type;
rettype result = first;
(void)std::initializer_list<int>{((f(v) < f(result)) ? (result = static_cast<rettype>(v), 0) : 0)...};
return result;
}

或者,如果您想避免不必要地调用 f :

template <typename F, typename FirstT, typename... FIn>
auto min_on(F f, const FirstT& first, const FIn&... v)
-> typename std::common_type<FirstT, FIn...>::type
{
using rettype = typename std::common_type<FirstT, FIn...>::type;
rettype result = first;
auto result_trans = f(result);
auto v_trans = result_trans;
(void)std::initializer_list<int>{(
(v_trans = f(v), v_trans < result_trans)
? (result = static_cast<rettype>(v), result_trans = v_trans, 0) : 0)...};
return result;
}

关于c++ - 初始化列表奇怪地取决于参数的顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37909146/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com