Templates 重载模板函数演绎错误
我努力做到这一点。我想创建重载模板函数,使此类调用成为可能并正确(GMock):Templates 重载模板函数演绎错误,templates,c++17,variadic-templates,sfinae,generic-lambda,Templates,C++17,Variadic Templates,Sfinae,Generic Lambda,我努力做到这一点。我想创建重载模板函数,使此类调用成为可能并正确(GMock): ASSERT_EQ(最小(1,2,1); ASSERT_EQ(min(std::less(),3,2),2); 自动防抱死制动系统组件=[](自动el1,自动el2){ 返回标准::abs(el1)
ASSERT_EQ(最小(1,2,1);
ASSERT_EQ(min(std::less(),3,2),2);
自动防抱死制动系统组件=[](自动el1,自动el2){
返回标准::abs(el1)<标准::abs(el2);
};
断言等式(最小值(绝对值-1,-5),-1);
断言等式(最小值(4,3,2,1,1);
除此之外,一切都很好:
ASSERT_EQ(min(std::less<>(), 3,2,1), 2);
ASSERT_EQ(min(std::less(),3,2,1),2);
当我提取函数本身以得到一个有意义的错误时:
min(std::less<>(), 3,2,1)
min(标准::less(),3,2,1)
我明白了:
In file included from /home/rumcajs/CLionProjects/ModernCppChallenge/tst/lang/container_minimum_test.cpp:4:
/home/rumcajs/CLionProjects/ModernCppChallenge/tst/lang/../../src/lang/container_minimum.h: In instantiation of ‘First cppchallenge::lang::min(First, Args ...) [with First = int; Args = {}; <template-parameter-1-3> = std::enable_if<true, void>]’:
/home/rumcajs/CLionProjects/ModernCppChallenge/tst/lang/../../src/lang/container_minimum.h:17:30: required from ‘First cppchallenge::lang::min(First, Args ...) [with First = std::less<void>; Args = {int}; <template-parameter-1-3> = std::enable_if<false, void>]’
/home/rumcajs/CLionProjects/ModernCppChallenge/tst/lang/../../src/lang/container_minimum.h:17:19: required from ‘First cppchallenge::lang::min(First, Args ...) [with First = std::less<void>; Args = {int, int, int}; <template-parameter-1-3> = std::enable_if<false, void>]’
/home/rumcajs/CLionProjects/ModernCppChallenge/tst/lang/container_minimum_test.cpp:40:33: required from here
/home/rumcajs/CLionProjects/ModernCppChallenge/tst/lang/../../src/lang/container_minimum.h:17:30: error: no matching function for call to ‘min()’
return min(first, min(args...));
~~~^~~~~~~~~
/home/rumcajs/CLionProjects/ModernCppChallenge/tst/lang/../../src/lang/container_minimum.h:8:7: note: candidate: ‘template<class T> T cppchallenge::lang::min(T, T)’
T min(T first, T second) {
^~~
/home/rumcajs/CLionProjects/ModernCppChallenge/tst/lang/../../src/lang/container_minimum.h:8:7: note: template argument deduction/substitution failed:
/home/rumcajs/CLionProjects/ModernCppChallenge/tst/lang/../../src/lang/container_minimum.h:17:30: note: candidate expects 2 arguments, 0 provided
return min(first, min(args...));
~~~^~~~~~~~~
/home/rumcajs/CLionProjects/ModernCppChallenge/tst/lang/../../src/lang/container_minimum.h:16:11: note: candidate: ‘template<class First, class ... Args, class> First cppchallenge::lang::min(First, Args ...)’
First min(First first, Args... args) {
^~~
/home/rumcajs/CLionProjects/ModernCppChallenge/tst/lang/../../src/lang/container_minimum.h:16:11: note: template argument deduction/substitution failed:
/home/rumcajs/CLionProjects/ModernCppChallenge/tst/lang/../../src/lang/container_minimum.h:17:30: note: candidate expects at least 1 argument, 0 provided
return min(first, min(args...));
~~~^~~~~~~~~
gmake[3]: *** [CMakeFiles/ModernCppChallengeLang.dir/build.make:102: CMakeFiles/ModernCppChallengeLang.dir/tst/lang/container_minimum_test.cpp.o] Error 1
gmake[2]: *** [CMakeFiles/Makefile2:116: CMakeFiles/ModernCppChallengeLang.dir/all] Error 2
gmake[1]: *** [CMakeFiles/Makefile2:128: CMakeFiles/ModernCppChallengeLang.dir/rule] Error 2
gmake: *** [Makefile:177: ModernCppChallengeLang] Error 2
包含在/home/rumcajs/CLionProjects/moderncppkchallenge/tst/lang/container\u minimum\u test.cpp:4中的文件中:
/home/rumcajs/CLionProjects/ModernCppChallenge/tst/lang/./../src/lang/container_minimum.h:在“第一个cppchallenge::lang::min(第一个,Args…[with First=int;Args={};=std::enable_if]”的实例化中:
/home/rumcajs/CLionProjects/ModernCppChallenge/tst/lang/./../src/lang/container_minimum.h:17:30:从“第一个cppchallenge::lang::min(第一个,Args…[with First=std::less;Args={int};=std::enable_if]开始需要”
/home/rumcajs/CLionProjects/ModernCppChallenge/tst/lang/./../src/lang/container_minimum.h:17:19:从'First cppchallenge::lang::min(First,Args…[with First=std::less;Args={int,int,int};=std::enable_if]开始需要'
/home/rumcajs/CLionProjects/moderncppkchallenge/tst/lang/container\u minimum\u test.cpp:40:33:从这里开始需要
/home/rumcajs/CLionProjects/moderncpchallenge/tst/lang/../../src/lang/container_minimum.h:17:30:错误:调用“min()时没有匹配的函数”
返回最小值(第一个,最小值(参数…);
~~~^~~~~~~~~
/home/rumcajs/CLionProjects/ModernCppChallenge/tst/lang/../../src/lang/container_minimum.h:8:7:注意:候选者:'template-cppchallenge::lang::min(T,T)'
T最小值(T第一,T第二){
^~~
/home/rumcajs/CLionProjects/moderncpchallenge/tst/lang/../../src/lang/container_minimum.h:8:7:注意:模板参数推断/替换失败:
/home/rumcajs/CLionProjects/moderncpchallenge/tst/lang/../../src/lang/container_minimum.h:17:30:注意:候选人需要2个参数,提供0个参数
返回最小值(第一个,最小值(参数…);
~~~^~~~~~~~~
/home/rumcajs/CLionProjects/ModernCppChallenge/tst/lang/../../src/lang/container_minimum.h:16:11:注意:候选:“模板第一个CPPCChallenge::lang::min(第一个参数…)
第一分钟(第一分钟,Args…Args){
^~~
/home/rumcajs/CLionProjects/moderncpchallenge/tst/lang/../../src/lang/container_minimum.h:16:11:注意:模板参数推断/替换失败:
/home/rumcajs/CLionProjects/moderncpchallenge/tst/lang/../../src/lang/container_minimum.h:17:30:注意:候选者至少需要1个参数,提供0个
返回最小值(第一个,最小值(参数…);
~~~^~~~~~~~~
gmake[3]:***[CMakeFiles/moderncpchallengelang.dir/build.make:102:CMakeFiles/moderncpchallengelang.dir/tst/lang/container\u minimum\u test.cpp.o]错误1
gmake[2]:***[CMakeFiles/Makefile2:116:CMakeFiles/moderncpchallengelang.dir/all]错误2
gmake[1]:***[CMakeFiles/Makefile2:128:CMakeFiles/moderncpchallengelang.dir/rule]错误2
gmake:**[Makefile:177:ModernCppChallengeLang]错误2
模板功能如下:
namespace cppchallenge::lang {
//#1
template<typename T>
T min(T first, T second) {
return first < second ? first : second;
}
template<typename First, typename... Args>
using are_same = std::conjunction<std::is_same<First, Args>...>;
//#2
template<typename First, typename... Args, typename = std::enable_if<are_same<First, Args...>::value, void>>
First min(First first, Args... args) {
return min(first, min(args...));
}
//#3
template<typename Comparator, typename T>
T min(Comparator comp, T first, T second) {
return comp(first, second) ? first : second;
}
//#4
template<typename Comparator, typename First, typename... Args,
typename = std::enable_if<are_same<First, Args...>::value, void>,
typename std::enable_if<std::is_convertible<Comparator, std::function<bool(First,First)>>::value>::type>
First min(Comparator comp, First first, Args... args) {
return min(comp, first, min(comp, args...));
}
}
namespace cppcchallenge::lang{
//#1
模板
T最小值(T第一,T第二){
返回第一个<第二个?第一个:第二个;
}
模板
使用are_same=std::连词;
//#2
模板
第一分钟(第一分钟,Args…Args){
返回最小值(第一个,最小值(参数…);
}
//#3
模板
T最小值(比较器补偿,T第一,T第二){
返回薪酬(第一,第二)?第一:第二;
}
//#4
模板
第一分钟(比较器补偿、第一优先、参数…参数){
返回最小值(comp,first,min(comp,args…);
}
}
错误指向函数#2,尽管它应该使用#4。我想错误在以下模板函数中:您必须在最后一个
之后添加*=nullptr
:type
template<typename Comparator, typename First, typename... Args,
typename = std::enable_if<are_same<First, Args...>::value, void>,
typename std::enable_if<std::is_convertible<Comparator, std::function<bool(First,First)>>::value>::type * = nullptr> // add * = nullptr
First min(Comparator comp, First first, Args... args) {
return comp(comp, first, min(comp, args...));
}
最后一个void
本身没有意义(前面的std::enable\u如果没有多大用处;但这是另一个问题;请参阅下面的“奖金建议”)
您应该在类似于
template <typename Comparator, typename First, typename ... Args,
typename = std::enable_if<are_same<First, Args...>::value, void>
void * = nullptr>
//............^^^^^^^^^^^^
否则,测试将无法工作,并且该功能将一直处于启用状态(从First
和Args…
类型的角度来看)
SFINAE测试中的类似问题
First min(First first, Args... args)
你确定第四种方法可用吗?你传递一个模板lambda并尝试将其转换为一个非模板。不幸的是,我不确定,情况就是这样。我想指定第一个参数是一个比较器,而不是要比较的值列表的第一个元素。我认为这是一种解决方案,但我愿意接受建议ns.您是否尝试过使用命名模板函数?您有什么想法?更改函数的名称?我特别希望避免放弃重载。template bool abs_comp(tel1,tel2){return std::abs(el1)std::is_convertable::value
,它可以工作。为什么添加*=nullptr
?@AmirRasulov-是的,std::is_convertable::value
本身可以工作;但是您必须在函数的模板签名上下文中看到它;我已经改进了答案;我希望现在如果更清楚。@LeśnyRumcajs-还可以检查其他SFINAE测试:有时当您应该使用std::enable_if
时,您可以使用std::enable_if_if_t
@max66,谢谢您的解释!如果我理解问题是在typename std::enable_if::type>
中忘记的=
?@AmirRasulov-忘记的typename=/code>befofo的再利用
template <typename Comparator, typename First, typename ... Args,
typename = std::enable_if<are_same<First, Args...>::value, void>
void * = nullptr>
//............^^^^^^^^^^^^
template <typename Comparator, typename First, typename ... Args,
typename = std::enable_if<are_same<First, Args...>::value, void>,
typename = void>
//........^^^^^^^^^^^
typename = std::enable_if_t<are_same<First, Args...>::value, void>
// ......................^^
typename = std::enable_if_t<are_same<First, Args...>::value>
First min(First first, Args... args)