请考虑以下功能模板:
$('.list-guides .select').on('click', function() {
$(this).parent().toggleClass('active');
if($(this).parent().hasClass('active')){
var $title = $('.active').find('.title').text();
alert($title);
var $preco = 9.90;
alert($preco);
}
return false;
});
以及以下功能:
<div class="details">
<div class="content-details">
<p class="title">Detalhes da Compra</p>
<div class="content">
<div class="product">
<p class="name"><span class="font-weight-bolder">1x</span> Competências Gerais na BNCC - R$17</p>
<hr/>
<div class="container">
<div class="row">
<!--frete-->
<div class="col-xl-6 col-lg-6 col-md-6 col-6">
<p class="field">Frete:</p>
</div>
<div class="col-xl-6 col-lg-6 col-md-6 col-6">
<p class="shipp float-right">Grátis</p>
</div>
</div>
<!--fim frete / início desconto-->
<div class="row">
<div class="col-xl-6 col-lg-6 col-md-6 col-6">
<p class="field">Desconto:</p>
</div>
<div class="col-xl-6 col-lg-6 col-md-6 col-6">
<p class="discount float-right">-R$7.10</p>
</div>
</div>
<!--fim desconto / início Total-->
<div class="row row-total">
<div class="col-xl-6 col-lg-6 col-md-6 col-6">
<p class="field font-weight-bolder">Total:</p>
</div>
<div class="col-xl-6 col-lg-6 col-md-6 col-6">
<p class="total float-right">R$9.90</p>
</div>
</div>
<div class="row row-next">
<div class="col-xl-12 col-lg-12 col-md-12 col-12">
<p class="field-btn text-center"><a href="#" class="button" target="_blank">Prosseguir</a></p>
</div>
</div>
</div>
<p class="no-product text-center">Nenhum produto selecionado</p>
</div>
</div>
</div>
</div>
为什么会发生以下情况:
template<typename RetType, typename... ArgTypes>
void foo0(std::function<RetType(ArgTypes...)> f) {}
template<typename RetType, typename ArgType>
void foo1(std::function<RetType(ArgType)> f) {}
编译错误是(带有C ++ 17的gcc-8):
void bar(int n) {}
使用虚拟模板
foo0<void, int>(bar); // does not compile
foo1<void, int>(bar); // compiles fine
使error: no matching function for call to 'foo0<void, int>(void (&)(int))'
foo0<void, int>(bar);
^
note: candidate: 'template<class RetType, class ... ArgTypes> void foo0(std::function<_Res(_ArgTypes ...)>)'
void foo0(std::function<RetType(ArgTypes...)> f) {}
^~~~
note: template argument deduction/substitution failed:
note: mismatched types 'std::function<void(_ArgTypes ...)>' and 'void (*)(int)'
foo0<void, int>(bar);
在gcc-8中可以正常编译,但是在Apple LLVM版本10.0.0(clang-1000.11.45.5)中使用clang会出错。
叮当声错误是
template<typename T>
void bar(int n) {}
答案 0 :(得分:1)
为什么会发生以下情况?
打电话时记入
foo0<void, int>(bar); // compilation error
foo1<void, int>(bar); // compile
foo0()
和foo1()
期望std::function
,而bar
是指向可以转换为std::function
但不是std::function
。
在foo1()
情况下,您同时显露了RetType
和ArgType
模板参数,因此编译器可以将bar
转换为std::function<void(int)>
,一切正常
但是foo0()
的情况有所不同,因为模板参数ArgTypes...
是一个可变参数,调用foo0<void, int>(bar)
不会显式显示完整的ArgTypes...
可变参数列表,而只显示第一种。
如果我没记错的话,问题是编译器尝试从ArgTypes...
参数推导出bar
的其余部分,但是bar
不是std::function
因此编译器无法推断出ArgTypes...
的其余部分,因此会出错。
我想是
foo0<void, int>(std::function<void(int)>{bar});
或者简单地
foo0(std::function<void(int)>{bar});
或(仅C ++ 17)
foo0(std::function{bar});
应进行编译,因为以这种方式调用foo0()
时,该函数会收到一个std::function
,以便编译器可以完全推断出模板参数。
我不明白带有虚拟模板参数的bar()
的版本
foo0<void, int>(bar<int>);
可以用g ++-8编译,我想这是g ++错误。
答案 1 :(得分:1)
template<typename RetType, typename... ArgTypes>
void foo0(std::function<RetType(ArgTypes...)> f) {}
解决方法是:
template<class X>struct tag_t{using type=X;};
template<class X>using block_deduction = typename tag_t<X>::type;
template<typename RetType, typename... ArgTypes>
void foo0(block_deduction_t<std::function<RetType(ArgTypes...)>> f) {}
,现在您的foo0<void, int>(bar)
会进行编译。
一般的问题是,说foo0<void, int>
,不是说“ RetType
是void
,而ArgTypes...
是int
,而是说{{ 1}} 以 ArgTypes...
开头。
int
以上编译正常。
...
c++17中的另一种方法是添加另一个重载。
离开这个:
std::function<void(int, double)> x;
foo0<void, int>( x )
但添加:
template<typename RetType, typename... ArgTypes>
void foo2(block_deduction_t<std::function<RetType(ArgTypes...)>> f) {}
在这里,我们将template<typename RetType, typename... ArgTypes, class F>
void foo2(F&& f) {
return foo2<RetType, ArgTypes...>( std::function{std::forward<F>(f)} );
}
template<int unused, class F>
void foo2(F&& f) {
return foo2( std::function{std::forward<F>(f)} );
}
包装到构造指导的F
中。
您对std::function
的调用现在将调用foo2<int, void>( bar )
,这是第二个重载。然后它继续从中构造一个foo2<void, int, decltype(bar)&>
,只要签名完全匹配就可以。