我似乎无法弄清楚我哪里出错了。 见https://ideone.com/WKsZSN
我正在尝试创建一个函数,只有当它的参数是某种模板类暴露一个itdef for iterator时才存在。
在非条件情况下,函数看起来像这样:
public String scene = new String();
public int number;
private void jButtonAPerformed(java.awt.event.ActionEvent evt){
scene = "A";
number+=1;
}
private void jButtonBPerformed(java.awt.event.ActionEvent evt){
scene = "B";
number+=1;
}
Location l = new Locaation(scene, number);
在这种情况下,类型推导适用于此代码段:
template<template <class, class> class C, class T, class A>
void DoSomething(C<T,A>& val)
{
T* pT;
cout << "did something!\n";
}
确定。所以现在我想输入-deduce我的参数和enable_if容器类暴露typedef迭代器。使用草药sutter得到了sfinae模式,我创造了:
vector<int> v{1,2,3,4,5};
DoSomething(v);
好的,所以使用这个,我现在可以检测是否暴露了迭代器:
template<class T> struct supports_iteration
{
private:
typedef char yes[1];
typedef char no[2];
template <class C> static yes& foo(typename C::iterator*);
template <class C> static no& foo(...);
public:
static constexpr bool value = sizeof(foo<T>(0)) == sizeof(yes);
};
工作正常并输出:
vector<int> v{1,2,3,4,5};
DoSomething(v);
cout << "vector<int> supports_iteration? " <<
boolalpha << supports_iteration<decltype(v)>::value << "!" << endl;
好的,现在我想使用enable_if升级DoSomething(),如下所示:
did something!
vector<int> supports_iteration? true!
但这不起作用。我得到了
prog.cpp:在函数'int main()'中: prog.cpp:44:22:错误:没有匹配函数来调用'DoSomethingSmartly(std :: vector&amp;)' DoSomethingSmartly(v); // - 失败! ^ prog.cpp:26:6:注意:候选人:模板类C,类T,A类&gt; void DoSomethingSmartly(typename std :: enable_if&gt; :: value&gt; :: type&amp;) void DoSomethingSmartly( ^ ~~~~~~~~~~~~~~~~~ prog.cpp:26:6:注意:模板参数扣除/替换失败: prog.cpp:44:22:注意:无法推导模板参数'模板类C' DoSomethingSmartly(v); // - 失败!!
我做错了什么?
答案 0 :(得分:2)
在您的尝试中,C
,T
,A
处于不可导出的上下文中(在traits<T>::type
,T
in in non deducible context),您可以在返回类型上使用enable_if
:
template<template <class, class> class C, class T, class A>
typename std::enable_if<supports_iteration<C<T,A>>::value>::type
DoSomethingSmartly(C<T, A>& val)
{
// ...
}
答案 1 :(得分:1)
@ Jarod42在他的评论中给出了正确答案,但我将以外行人的名义加上这一点:
只考虑......
template<template <class, class> class C, class T, class A>
void DoSomethingSmartly(
typename std::enable_if<
supports_iteration<C<T,A>>::value>::type&);
...编译器无法从向量参数中推导出C,T,A的类型,因为C<T,A>
中的support_iteration<C<T,A>>::value
处于不可推导的上下文中。
This answer更详细地解释了它。
以下更改可解决此问题:
template<template <class, class> class C, class T, class A>
void DoSomethingSmartly(
C<T,A>& c, //Now deducible...
typename std::enable_if<supports_iteration<C<T,A>>::value>::type* = 0)
{
T* pT;
cout << "did something smartly!\n";
}
现在第一个参数用于推导C,T,A,第二个参数用于确定函数是否可以基于SFINAE调用。使用* = 0
以便您永远不必传递附加参数。
答案 2 :(得分:0)
我明白了。我真正想要的是这个(我实际上并不关心迭代,它是暴露语法T :: size()函数的不良代理):
template<template <class, class> class C, class T, class A,
typename = decltype(
declval<C<T,A>>().size()
,void()
)
>
void DoSomethingReallySmartly(C<T,A>& val)
{
T* pT;
cout << "did something really smartly!\n";
}
...但我仍然想知道为什么类型演绎在原始尝试中失败了!!!