候选函数不可行:没有从std :: vector <derived>到std :: vector <base>的转换

塞岑

首先,标题可能无法反映当前问题,因此请随时进行更改。假设我有以下课程;

#include <iostream>
#include <vector>

template <typename K, class V>
class A {
public:
  K x;
  V y;
  A(K x, V y):x(x), y(y) {}
  void print(A<K, V>& z) {
    std::cout << x + z.x << "-" << y + z.y << std::endl;
  }
  void print(std::vector<A<K,V>> z) {
    for(auto& i:z) {
      print(i);
    }
  }
};

class B:public A<int, std::string> {
public:
  B():A(0, "zero") {}
  B(int x, std::string y):A(x, y) {}
};

void test() {
  B b1(1, "one");
  B b2(2, "two");
  B b3(3, "three");
  B b4(4, "four");
  B b5(5, "five");
  b5.print(b1);
  //
  std::vector<B> c;
  c.push_back(b1);
  c.push_back(b2);
  c.push_back(b3);
  c.push_back(b4);
  b5.print(c);
}

我在最后一行(b5.print(c)处收到以下错误

test_class.cpp:40:6: error: no matching member function for call to 'print'
  b5.print(c);
  ~~~^~~~~
test_class.cpp:10:8: note: candidate function not viable: no known conversion from 'std::vector<B>' to 'A<int, std::__1::basic_string<char> > &' for 1st argument
  void print(A<K, V>& z) {
       ^
test_class.cpp:13:8: note: candidate function not viable: no known conversion from 'vector<B>' to 'vector<A<int, std::__1::basic_string<char> >>' for 1st argument
  void print(std::vector<A<K,V>> z) {
       ^
1 error generated.

我基本上希望从隐式转换vector<B>std::vector<A<int,std::string>>但不是。因此,我提出了两个解决方案。

  1. typedef std::vector<A<int,std::string>> MyWeirdVector;在A类中定义,并使用seB::MyWeirdVector c;代替std::vector<B> c;
  2. template <typename U>在A类中定义每个打印函数,并接受类型名U作为参数。

两种解决方案都有其自身的缺点。首先,我必须将C实例化为B :: MyWeirdVector,其次,我(感觉)没有类型安全性。即使我未在中定义type,第二个解决方案也可以工作<>

那么,是否有解决此问题的优雅方法,例如允许将隐式类型转换从转换std::vector<B>std::vector<A<int,std::string>>

-编辑-

感谢@ max66和@Caleth等人。我只想分享完整的工作示例。请注意,如果您不想发疯,@ max66的答案是没有void以前print的。(1.所有打印功能参数均为const。2.合并@ max66和@Caleth的答案。)

#include <iostream>
#include <vector>
#include <type_traits>

template <typename K, class V>
class A {
public:
  K x;
  V y;
  A(K x, V y):x(x), y(y) {}
  void print(const A<K, V>& z) {
    std::cout << x + z.x << "-" << y + z.y << std::endl;
  }

  // for C++11, thanks to @Caleth
  // template <typename Container, typename = typename std::enable_if<!std::is_base_of< A<K,V>, typename std::remove_reference<Container>::type >::value>::type>
  // void print(Container&& z) {
  //   for(auto& i:z) {
  //     print(i);
  //   }
  // }

  // thanks to @max66
  template <typename T>
  typename std::enable_if<std::is_base_of<A<K, V>, T>::value>::type
    print(std::vector<T> const & z) {
      for(auto const & i:z) print(i);
    }    
  };

class B:public A<int, std::string> {
public:
  B():A(0, "zero") {}
  B(int x, std::string y):A(x, y) {}
};

void test() {
  B b1(1, "one");
  B b2(2, "two");
  B b3(3, "three");
  B b4(4, "four");
  B b5(5, "five");
  b5.print(b1);
  //
  std::vector<B> c;
  c.push_back(b1);
  c.push_back(b2);
  c.push_back(b3);
  c.push_back(b4);
  b5.print(c);
}
最高66

关于什么

template <typename T>
void print(std::vector<T> const & z) {
  for(auto const & i:z) {
    print(i);
  }
}

代替

void print(std::vector<A<K,V>> z) {
  for(auto& i:z) {
    print(i);
  }
}

我的意思是:您不能进行从std::vector<B>的隐式转换std::vector<A<K, T>>但是您可以管理泛型std::vector<T>(generic T的内容并获得(以防万一)从T元素到的隐式转换A<K, T>(如果T是派生类型)。

如果需要,您可以添加std::enable_if仅当T从派生时启用模板打印功能A<K, T>

-编辑-

OP问

如何使用std::enable_if启用模板打印功能以仅对从A派生的对象进行操作?

有很多方法。举例来说,请参见Caleth的答案以及其他模板类型,并std::enable_if激活它。

但我更喜欢由激活的返回值std::enable_if

表示为(警告:未经测试的代码)

template <typename T>
typename std::enable_if<std::is_base_of<A<K, V>, T>::value>::type
   print(std::vector<T> const & z)
 { for(auto const & i:z) print(i); }

如果您可以使用C ++ 14,则可以进行一些简化(使用std::enable_if_t<>代替typename std::enable_if<>::type

template <typename T>
std::enable_if_t<std::is_base_of<A<K, V>, T>::value>
   print(std::vector<T> const & z)
 { for(auto const & i:z) print(i); }

并多使用C ++ 17(std::is_base_of_v<>而不是`std :: is_base_of <> :: value)

template <typename T>
std::enable_if_t<std::is_base_of_v<A<K, V>, T>>
   print(std::vector<T> const & z)
 { for(auto const & i:z) print(i); }

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

C ++ lambda转换-为什么候选构造函数不可行:没有已知的从lambda到std :: function的转换

来自分类Dev

C++ V 形转换:vector<Base1> 到 vector<Derived> 到 vector<Base2>

来自分类Dev

在使用std :: vector <Base *>来存储Derived *时如何指定

来自分类Dev

C++ - 候选函数不可行:没有已知的从“struct”到“struct (&)”的转换

来自分类Dev

没有从 '__wrap_iter<std::__1::vector<MenuItem *>::const_pointer>' 到 '__wrap_iter<std::__1::vector<MenuItem>::pointer>' 的可行转换

来自分类Dev

NSMutableArray到std :: vector

来自分类Dev

将std :: vector <std :: vector <std :: string >>转换为std :: vector <std :: vector <double >>

来自分类Dev

std :: vector <int>到std :: vector <enum>

来自分类Dev

c++14 中从“const std::vector<cv::Mat>*”到“std::vector<cv::Mat>*”的无效转换

来自分类Dev

没有可行的重载 '=' 在 std::vector

来自分类Dev

使用std :: count_if()时,错误“没有从'std :: vector <double,std :: allocator <double>>'到'double *'的未知转换?

来自分类Dev

std::vector 转换为 std::map

来自分类Dev

std :: vector如何转换为std :: span?

来自分类Dev

C++:候选函数不可行:第一个参数没有从“Segment [2]”到“int *”的已知转换

来自分类Dev

从std :: vector到adept :: avector

来自分类Dev

如何将std :: vector <vector>转换为void *

来自分类Dev

C ++:错误无法从std :: vector <int> *转换为std :: vector <std :: vector <int>>

来自分类Dev

C++ V 形转换:vector<Base1*> 到 vector<Base2*>

来自分类Dev

ByteString到Vector的转换

来自分类Dev

如何从std :: vector转换为args

来自分类Dev

从Boost Hana Tuple转换为Std Vector

来自分类Dev

隐式转换为std :: vector

来自分类Dev

将 malloc 转换为 new 或 std::vector

来自分类Dev

从std :: vector <int>转换为char [] C ++

来自分类Dev

将 std::vector<T> 转换为 char *

来自分类Dev

如何放置到std :: array的std :: vector?

来自分类Dev

有什么快速方法可以将std :: vector <std :: vector <float >>转换为std :: vector <float2>?

来自分类Dev

没有从“int [nums.size()]”类型的返回值到函数返回类型“vector<int>”的可行转换

来自分类Dev

将std :: vector <char>转换为std :: vector <T>转换c ++

Related 相关文章

  1. 1

    C ++ lambda转换-为什么候选构造函数不可行:没有已知的从lambda到std :: function的转换

  2. 2

    C++ V 形转换:vector<Base1> 到 vector<Derived> 到 vector<Base2>

  3. 3

    在使用std :: vector <Base *>来存储Derived *时如何指定

  4. 4

    C++ - 候选函数不可行:没有已知的从“struct”到“struct (&)”的转换

  5. 5

    没有从 '__wrap_iter<std::__1::vector<MenuItem *>::const_pointer>' 到 '__wrap_iter<std::__1::vector<MenuItem>::pointer>' 的可行转换

  6. 6

    NSMutableArray到std :: vector

  7. 7

    将std :: vector <std :: vector <std :: string >>转换为std :: vector <std :: vector <double >>

  8. 8

    std :: vector <int>到std :: vector <enum>

  9. 9

    c++14 中从“const std::vector<cv::Mat>*”到“std::vector<cv::Mat>*”的无效转换

  10. 10

    没有可行的重载 '=' 在 std::vector

  11. 11

    使用std :: count_if()时,错误“没有从'std :: vector <double,std :: allocator <double>>'到'double *'的未知转换?

  12. 12

    std::vector 转换为 std::map

  13. 13

    std :: vector如何转换为std :: span?

  14. 14

    C++:候选函数不可行:第一个参数没有从“Segment [2]”到“int *”的已知转换

  15. 15

    从std :: vector到adept :: avector

  16. 16

    如何将std :: vector <vector>转换为void *

  17. 17

    C ++:错误无法从std :: vector <int> *转换为std :: vector <std :: vector <int>>

  18. 18

    C++ V 形转换:vector<Base1*> 到 vector<Base2*>

  19. 19

    ByteString到Vector的转换

  20. 20

    如何从std :: vector转换为args

  21. 21

    从Boost Hana Tuple转换为Std Vector

  22. 22

    隐式转换为std :: vector

  23. 23

    将 malloc 转换为 new 或 std::vector

  24. 24

    从std :: vector <int>转换为char [] C ++

  25. 25

    将 std::vector<T> 转换为 char *

  26. 26

    如何放置到std :: array的std :: vector?

  27. 27

    有什么快速方法可以将std :: vector <std :: vector <float >>转换为std :: vector <float2>?

  28. 28

    没有从“int [nums.size()]”类型的返回值到函数返回类型“vector<int>”的可行转换

  29. 29

    将std :: vector <char>转换为std :: vector <T>转换c ++

热门标签

归档