C++ C++;使用继承检测惯用语失败
下面的代码无法编译。由于某种原因,从C++ C++;使用继承检测惯用语失败,c++,variadic-templates,template-meta-programming,sfinae,template-argument-deduction,C++,Variadic Templates,Template Meta Programming,Sfinae,Template Argument Deduction,下面的代码无法编译。由于某种原因,从HasFoo继承会导致IsWrapper失败。它与friend函数foo()有关,因为从其他类继承似乎可以正常工作。我不明白为什么从HasFoo继承会导致检测习惯用法失败 用foo作为包装器检测的正确方法是什么 #包括 #包括 模板 结构包装器{ 价值类型V; }; //定义一些有用的元函数。 模板 T BaseTypeImpl(常量包装器&); 模板 使用BaseType=decltype(BaseTypeImpl(std::declval()); 模板
HasFoo
继承会导致IsWrapper
失败。它与friend
函数foo()
有关,因为从其他类继承似乎可以正常工作。我不明白为什么从HasFoo
继承会导致检测习惯用法失败
用foo作为包装器
检测的正确方法是什么
#包括
#包括
模板
结构包装器{
价值类型V;
};
//定义一些有用的元函数。
模板
T BaseTypeImpl(常量包装器&);
模板
使用BaseType=decltype(BaseTypeImpl(std::declval());
模板
标记TagTypeImpl(const-Wrapper&);
模板
使用TagType=decltype(TagTypeImpl(std::declval());
//定义VoidT。C++17不需要。
模板
使用void t=void;
//定义已检测的。
模板
结构IsDetectedImpl
:std::false_type{};
模板
结构IsDetectedImpl
:std::true_type{};
模板
使用IsDetect=typename IsDetectedImpl::type;
//如果类型派生自包装器,则定义IsWrapper true。
模板
使用IsWrapperImpl=
std::是的基础;
模板
使用IsWrapper=IsDetected;
//混血儿。
模板
结构HasFoo{
模板
朋友void foo(const T&This,const V&Other){
标准::cout
我不明白为什么从HasFoo
继承会导致检测习惯用法失败
我也不完全清楚,但肯定有一个问题是,您在HasFoo
的主体中使用IsWrapper
,并且当您从WithFoo
继承HasFoo
时,当您使用IsWrapper
检查它时,WithFoo
是不完整的
一个可能的解决方案(我不知道您是否接受)是定义(和SFINAE启用/禁用)foo()
outsideHasFoo
我的意思是…试着重写HasFoo,如下所示
template <typename T>
struct HasFoo {
template <typename V>
friend void foo(const T &This, const V &Other);
};
用foo作为包装进行检测的正确方法是什么
对不起,你的代码对我来说太复杂了
我提出以下(我希望更简单)备选方案
#include <type_traits>
#include <iostream>
template<typename TagType, typename ValueType>
struct Wrapper {
ValueType V;
};
template <typename T1, typename T2>
constexpr std::true_type IW_helper1 (Wrapper<T1, T2> const &);
template <typename T>
constexpr auto IW_helper2 (T t, int) -> decltype( IW_helper1(t) );
template <typename T>
constexpr std::false_type IW_helper2 (T, long);
template <typename T>
using IsWrapper = decltype(IW_helper2(std::declval<T>(), 0));
template <typename T>
struct HasFoo {
template <typename V>
friend void foo(const T &This, const V &Other);
};
template <typename T, typename V>
std::enable_if_t<IsWrapper<T>::value && IsWrapper<V>::value>
foo(const T &This, const V &Other) {
std::cout << typeid(This).name() << " and " << typeid(Other).name()
<< " are wrappers\n";
}
template<typename Tag>
struct WithFoo : public Wrapper<WithFoo<Tag>, int>,
public HasFoo<WithFoo<Tag>> {};
int main () {
struct Tag {};
WithFoo<Tag> WrapperFooV;
static_assert(IsWrapper<decltype(WrapperFooV)>::value,
"Not a wrapper");
}
#包括
#包括
模板
结构包装器{
价值类型V;
};
模板
constepr std::true_type IW_helper1(Wrapper const&);
模板
constexpr auto IW_helper2(T,int)->decltype(IW_helper1(T));
模板
constexpr std::false_类型IW_helper2(T,long);
模板
使用IsWrapper=decltype(IW_helper2(std::declval(),0));
模板
结构HasFoo{
模板
朋友void foo(const T&This,const V&Other);
};
模板
std::如果启用,则启用
foo(常数T和此、常数V和其他){
好吧,我想这是我能做到的最低限度了。
template <typename T, typename V>
std::enable_if_t<IsWrapper<T>::value && IsWrapper<V>::value>
foo(const T &This, const V &Other) {
std::cout << typeid(This).name() << " and " << typeid(Other).name()
<< " are wrappers\n";
}
#include <type_traits>
#include <iostream>
template<typename TagType, typename ValueType>
struct Wrapper {
ValueType V;
};
template <typename T1, typename T2>
constexpr std::true_type IW_helper1 (Wrapper<T1, T2> const &);
template <typename T>
constexpr auto IW_helper2 (T t, int) -> decltype( IW_helper1(t) );
template <typename T>
constexpr std::false_type IW_helper2 (T, long);
template <typename T>
using IsWrapper = decltype(IW_helper2(std::declval<T>(), 0));
template <typename T>
struct HasFoo {
template <typename V>
friend void foo(const T &This, const V &Other);
};
template <typename T, typename V>
std::enable_if_t<IsWrapper<T>::value && IsWrapper<V>::value>
foo(const T &This, const V &Other) {
std::cout << typeid(This).name() << " and " << typeid(Other).name()
<< " are wrappers\n";
}
template<typename Tag>
struct WithFoo : public Wrapper<WithFoo<Tag>, int>,
public HasFoo<WithFoo<Tag>> {};
int main () {
struct Tag {};
WithFoo<Tag> WrapperFooV;
static_assert(IsWrapper<decltype(WrapperFooV)>::value,
"Not a wrapper");
}