C++ 在类主体外部定义的成员函数上的sfinae
有点像是我父亲的延续。我得到的是一组函数,它们形成了一个sfinae依赖链,就像这样(让“a->B”符号表示a的存在依赖于B的存在): 其中T是模板参数。它的实现方式如下: 在标有箭头的行上,GCC 4.7.1表示不满: 错误:“decltype(((S*)0)->S::f((*t_ptr)),void())S::f_base(const t*)”的原型与类中的任何原型都不匹配C++ 在类主体外部定义的成员函数上的sfinae,c++,templates,c++11,sfinae,decltype,C++,Templates,C++11,Sfinae,Decltype,有点像是我父亲的延续。我得到的是一组函数,它们形成了一个sfinae依赖链,就像这样(让“a->B”符号表示a的存在依赖于B的存在): 其中T是模板参数。它的实现方式如下: 在标有箭头的行上,GCC 4.7.1表示不满: 错误:“decltype(((S*)0)->S::f((*t_ptr)),void())S::f_base(const t*)”的原型与类中的任何原型都不匹配 错误:候选项是:模板decltype(((S*)this)->S::f((*t_ptr)),void())S::f_b
错误:候选项是:模板decltype(((S*)this)->S::f((*t_ptr)),void())S::f_base(const t*) 我试图通过在
std::declval()前面加上std::declval(),
来明确指定我在f_base
中使用的f
,但错误仍然存在
我知道我可以这样修改依赖关系图:
S::f_base ->
-> ns::f_ -> f -> T::f
S::f ->
要使S::f_base
与S::f
一起依赖于S::f
,但有没有办法用第一个依赖关系图来实现这一点?GCC 4.X不是元编程的最佳选择
我已设法使其在4.7.3()中编译:
#包括
结构;
模板
自动f(S&S,T const&T)->decltype(T.f(S),void())
{
t、 f(s);
}
名称空间ns
{
模板
自动f(S&S,T const&T)->decltype(f(S,T),void())
{
f(s,t);
}
}
//一些std::void\u不喜欢但与GCC4.x兼容
模板
结构无效\u t
{
使用type=typename std::enable_if::type;
};
结构
{
模板
auto f(T const&T)->decltype(ns::f_(std::declval(),T),void());
模板
auto f_base(T const*T_ptr)->typename void_T:type;
};
模板
自动S::f(T const&T)->decltype(ns::f_40; std::declval(),T),void())
{
ns::f_uz(*此,t);
}
//::f是必需的,如果只是“f”,则失败
模板
自动S::f_base(T const*T_ptr)->typename void_T::type
{
f(*t_ptr);
}
int main()
{
返回0;
}
注意:
在GCC4.X中,我看到了一些奇怪的东西,比如:
template<class T>
struct void_t
{
using type = void;
};
模板
结构无效\u t
{
使用类型=无效;
};
其中,GCC将void\u t::type
替换为void
,即使expr
无效。这就是为什么我使用这个void\u t
的实现,一个明显的问题:为什么要将定义移到类主体之外?@Xeo将接口和实现分开,至少在视觉上是这样,因为这些函数实际上比这里简化的一行程序大得多。第二个代码在Windows上与Clang r161057和GCC 4.6.3的libstdc++一起工作。似乎是GCC的一个bug,因为Clang编译很好(根据)。因为声明是完全相同的,所以不会想到其他任何事情。也使用VS2012编译。
#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;
}
S::f_base ->
-> ns::f_ -> f -> T::f
S::f ->
#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);
}
}
// some std::void_t like but GCC4.x compatible
template<class T>
struct void_t
{
using type = typename std::enable_if<std::is_same<T,T>::value >::type;
};
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) -> typename void_t< decltype (::f(*std::declval<T const*>()))>::type ;
};
template <typename T>
auto S::f(T const& t) -> decltype(ns::f_(std::declval<S&>(), t), void())
{
ns::f_(*this, t);
}
// ::f is needed, fail if just 'f'
template <typename T>
auto S::f_base(T const* t_ptr) -> typename void_t< decltype (::f(*std::declval<T const*>()))>::type
{
f(*t_ptr);
}
int main()
{
return 0;
}
template<class T>
struct void_t
{
using type = void;
};