Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 初始值设定项列表奇怪地依赖于参数的顺序?_C++_C++11_Lambda_Initializer List_Typetraits - Fatal编程技术网

C++ 初始值设定项列表奇怪地依赖于参数的顺序?

C++ 初始值设定项列表奇怪地依赖于参数的顺序?,c++,c++11,lambda,initializer-list,typetraits,C++,C++11,Lambda,Initializer List,Typetraits,我有以下代码片段: #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...>

我有以下代码片段:

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

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

如果
f(v)
,则函数将
result
设置为
v
。使用
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)...};
这显然是错误的。因此,也许您可以要求第一个参数:

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。完美答案!我不能要求更多了。非常感谢Benjamint这应该返回可选的,或者在空列表中失败。在编译时,您的建议在empty上失败,这很好。注意:通过跟踪答案的索引并在找到答案后切换回值,您可以不惜代价避免重复复制结果类型(可能会很昂贵!),但这是非常先进的。
[](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;
}
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;
}