【发布时间】:2012-08-01 11:49:22
【问题描述】:
是我previous question 的延续。我所拥有的是一堆形成像这样的sfinae依赖链的函数(让“A -> B”表示法意味着A的存在取决于B的存在):
S::f_base -> S::f -> ns::f_ -> f -> T::f
其中 T 是模板参数。它的实现类似于this:
#include <utility>
struct S;
template <typename T>
auto f(S& s, T const& t) -> decltype(t.f(s), void())
{
t.f(s);
}
namespace ns
{
template <typename T>
auto f_(S& s, T const& t) -> decltype(f(s, t), void())
{
f(s, t);
}
}
struct S
{
template <typename T>
auto f(T const& t) -> decltype(ns::f_(std::declval<S&>(), t), void())
{
ns::f_(*this, t);
}
template <typename T>
auto f_base(T const* t_ptr) -> decltype(f(*t_ptr), void())
{
f(*t_ptr);
}
};
struct pass
{
void f(S&) const
{
}
};
struct fail
{
};
int main()
{
S s;
s.f(pass()); // compiles
//s.f(fail()); // doesn't compile
return 0;
}
并按预期工作。当我尝试将S::f 和S::f_base 的定义移到类主体之外时出现问题,例如so:
#include <utility>
struct S;
template <typename T>
auto f(S& s, T const& t) -> decltype(t.f(s), void())
{
t.f(s);
}
namespace ns
{
template <typename T>
auto f_(S& s, T const& t) -> decltype(f(s, t), void())
{
f(s, t);
}
}
struct S
{
template <typename T>
auto f(T const& t) -> decltype(ns::f_(std::declval<S&>(), t), void());
template <typename T>
auto f_base(T const* t_ptr) -> decltype(f(*t_ptr), void());
};
template <typename T>
auto S::f(T const& t) -> decltype(ns::f_(std::declval<S&>(), t), void())
{
ns::f_(*this, t);
}
template <typename T>
auto S::f_base(T const* t_ptr) -> decltype(f(*t_ptr), void()) // <---- HERE ---
{
f(*t_ptr);
}
int main()
{
return 0;
}
在箭头标记的线上GCC 4.7.1表示不满意:
错误:'decltype ((((S*)0)->S::f((* t_ptr)), void())) S::f_base(const T*)' 的原型不匹配任何在“S”类
错误:候选是:模板 decltype ((((S*)this)->S::f((* t_ptr)), void())) S::f_base(const T*)
我试图通过在f_base 中添加std::declval<S&>(). 来明确指定我在f_base 中使用的f,但错误仍然存在。
我知道我可以像这样修改依赖图:
S::f_base ->
-> ns::f_ -> f -> T::f
S::f ->
使S::f_base 依赖于ns::f_ 和S::f,但是有没有办法用第一个依赖图做到这一点?
【问题讨论】:
-
显而易见的问题:您为什么想要将定义移到类主体之外?
-
@Xeo 将接口与实现分开,至少在视觉上是这样,因为这些功能实际上比这里简化的单行代码要大得多。
-
第二个代码在 Windows 上使用 Clang r161057 和 GCC 4.6.3 的 libstdc++。
-
似乎是 GCC 的一个错误,因为 Clang 编译得很好(根据 rubenvb)。不会想到别的,因为声明完全一样。
-
也可以用 VS2012 编译。
标签: c++ templates c++11 sfinae decltype