【发布时间】:2019-01-25 16:49:34
【问题描述】:
在编译以下 Try it out on Coliru! 时,我期待 GCC 不考虑该函数
template <typename DST, typename... Ts>
std::enable_if_t<sizeof...(Ts) == 0> CheckAndSetVal(DST&) {}
用于分析,因为 sizeof 条件不满足。
namespace SFINAE
{
template <typename DST, typename... Ts>
std::enable_if_t<sizeof...(Ts) == 0> CheckAndSetVal(DST&) {}
template <typename DST, typename T1, typename T2, typename... Ts>
std::enable_if_t<!std::is_same_v<DST, T2> > CheckAndSetVal(DST& dst, T1&& cond, T2&& val, Ts&&... ts)
{
if (cond())
dst = val();
else
CheckAndSetVal(dst, std::forward<Ts>(ts)...);
}
template <typename DST, typename T1, typename T2, typename... Ts>
std::enable_if_t<std::is_same_v<DST, T2> > CheckAndSetVal(DST& dst, T1&& cond, T2&& val, Ts&&... ts)
{
if (cond())
dst = val;
else
CheckAndSetVal(dst, std::forward<Ts>(ts)...);
}
template <typename DST, typename... Ts>
void SetValue(DST& dst, Ts&&... ts)
{
CheckAndSetVal(dst, std::forward<Ts>(ts)...);
}
}
int main()
{
int i = 0;
SFINAE::SetValue(i, []() { return true; } , []() { return 222; }
, []() { return false; } , 444
);
}
但我看到 GCC 抛出以下错误,恕我直言,这与它本身是矛盾的。它抱怨它找不到与 int&、lambda 和 int 作为参数的递归函数调用之一的匹配函数。但再次说候选人是应该被禁用的候选人,因为条件 sizeof...(Ts) == 0 是错误的。
candidate expects 1 argument, 3 provided
谁能帮我理解为什么会这样?
main.cpp: In instantiation of 'std::enable_if_t<(! is_same_v<DST, T2>)> SFINAE::CheckAndSetVal(DST&, T1&&, T2&&, Ts&& ...) [with DST = int; T1 = main()::<lambda()>; T2 = main()::<lambda()>; Ts = {main()::<lambda()>, int}; std::enable_if_t<(! is_same_v<DST, T2>)> = void]':
main.cpp:36:19: required from 'void SFINAE::SetValue(DST&, Ts&& ...) [with DST = int; Ts = {main()::<lambda()>, main()::<lambda()>, main()::<lambda()>, int}]'
main.cpp:47:19: required from here
main.cpp:21:21: error: no matching function for call to 'CheckAndSetVal(int&, main()::<lambda()>, int)'
CheckAndSetVal(dst, std::forward<Ts>(ts)...);
~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:13:40: note: candidate: 'template<class DST, class ... Ts> std::enable_if_t<(sizeof... (Ts) == 0)> SFINAE::CheckAndSetVal(DST&)'
std::enable_if_t<sizeof...(Ts) == 0> CheckAndSetVal(DST&) {}
^~~~~~~~~~~~~~
main.cpp:13:40: note: template argument deduction/substitution failed:
main.cpp:21:21: note: candidate expects 1 argument, 3 provided
CheckAndSetVal(dst, std::forward<Ts>(ts)...);
~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:16:47: note: candidate: 'template<class DST, class T1, class T2, class ... Ts> std::enable_if_t<(! is_same_v<DST, T2>)> SFINAE::CheckAndSetVal(DST&, T1&&, T2&&, Ts&& ...)'
std::enable_if_t<!std::is_same_v<DST, T2> > CheckAndSetVal(DST& dst, T1&& cond, T2&& val, Ts&&... ts)
^~~~~~~~~~~~~~
main.cpp:16:47: note: template argument deduction/substitution failed:
【问题讨论】:
-
Fwiw,这个问题的标题是完全错误的。 gcc 正在正确禁用该功能
-
我使用上面的标题来反映它在 VS2017 上编译得很好但在 GCC 上编译得很好。但是同样,标题中缺少关于 VS 的要点,这反过来又令人困惑。对不起……
标签: c++ c++17 variadic-templates sfinae enable-if