我似乎找不出哪里出错了。请参阅https://ideone.com/WKsZSN
我正在尝试创建一个仅当它的参数是某种模板类时才存在的函数,该模板类为迭代器提供了一个类型定义。
在非条件情况下,该函数将如下所示:
template<template <class, class> class C, class T, class A>
void DoSomething(C<T,A>& val)
{
T* pT;
cout << "did something!\n";
}在这种情况下,type-deduction可以很好地用于此代码片段:
vector<int> v{1,2,3,4,5};
DoSomething(v);好的。所以现在我想输入-deduce我的参数,并且enable_if容器类公开了typedef迭代器。使用herb sutter gotw sfinae模式,我创建了:
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;工作正常,输出:
did something!
vector<int> supports_iteration? true!好了,现在我想使用enable_if升级DoSomething(),如下所示:
template<template <class, class> class C, class T, class A>
void DoSomethingSmartly(
typename std::enable_if<
supports_iteration<
C<T,A>
>::value
>::type& val)
{
T* pT;
cout << "did something smartly!\n";
}但这不管用。我得到了
向量:在函数‘int main()’中: prog.cpp:44:22:错误:没有与调用‘DoSomethingSmartly(std::prog.cpp&)’匹配的函数DoSomethingSmartly(v);// -失败!!^ prog.cpp:26:6:注意:候选:模板类C,类T,类A>空类型(DoSomethingSmartly std::enable_if >::value>::type&)空DoSomethingSmartly( ^~ prog.cpp:26:6:注意:模板参数推导/替换失败: prog.cpp:44:22:注意:无法推导模板参数‘模板类C’DoSomethingSmartly(v);// -失败!!
我做错了什么?
发布于 2017-04-21 15:38:31
在您尝试中,C、T、A处于不可推断上下文中(在traits<T>::type中,T In处于不可推断上下文中),您可以在返回类型上使用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)
{
// ...
}发布于 2017-04-21 16:00:11
@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的类型,因为support_iteration<C<T,A>>::value中的C<T,A>处于不可推断的上下文中。
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,这样您就永远不需要传入额外的参数。
发布于 2017-04-21 15:27:12
我想通了。我真正想要的是这样的(我实际上并不关心迭代,它是暴露语法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";
}...but我还是想知道为什么类型推导在最初的尝试中失败了!
https://stackoverflow.com/questions/43536177
复制相似问题