Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;使用继承检测惯用语失败_C++_Variadic Templates_Template Meta Programming_Sfinae_Template Argument Deduction - Fatal编程技术网

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()
outside
HasFoo

我的意思是…试着重写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");
}