C++ 复杂物体的安放

C++ 复杂物体的安放,c++,templates,c++14,emplace,C++,Templates,C++14,Emplace,我试图在对象中实现“安放”功能。它的结构如下所示。我有一个模板对象,它将大小与模板类型配对。我希望能够在std库容器(例如向量)中就地构建这个。我没有使用std::pair,因为我的类B将提供有关数据的其他函数 我需要如何修改代码,以便像在main中一样调用emplace #include <iostream> #include <vector>

我试图在对象中实现“安放”功能。它的结构如下所示。我有一个模板对象,它将大小与模板类型配对。我希望能够在std库容器(例如向量)中就地构建这个。我没有使用
std::pair
,因为我的类
B
将提供有关数据的其他函数

我需要如何修改代码,以便像在main中一样调用emplace

#include <iostream>                                                                 
#include <vector>                                                                   
using namespace std;                                                                

class C {                                                                           
  public:                                                                           
    C(const string& _s) : s(_s) {}                                                  
    C(string&& _s) : s(_s) {}                                                       

  private:                                                                          
    string s;                                                                       
};                                                                                  

template<typename A>                                                                
class B {                                                                           
  public:                                                                           

    B(size_t _i, const A& _a) : i(_i), a(_a) {}                                     
    B(size_t _i, A&& _a) : i(_i), a(_a) {}                                                  

  private:                                                                          
    size_t i;                                                                       
    A a;                                                                            
};                                                                                  

int main() {                                                                        
  vector<B<C>> v;                                                                   
  v.emplace_back(5, "Hello");                                                       
}
#包括
#包括
使用名称空间std;
C类{
公众:
C(常量字符串&_-s):s(_-s){
C(字符串&&&us):s(&&us){
私人:
字符串s;
};                                                                                  
样板
B类{
公众:
B(大小,常数A和A):i(_i),A(_A){
B(大小(i,A&):i(i),A(A){
私人:
尺寸i;
A A;
};                                                                                  
int main(){
向量v;
v、 后置(5,“你好”);
}

每个参数允许一个用户定义的转换序列,您有两个:

  • const char*
    -->
    std::string
  • std::string
    -->
    C
  • 您可以通过实现通用转发构造函数来减少隐式转换的数量:

    template<typename A>                                                                
    class B {                                                                           
      public:
    
        template<typename X>
        B(size_t _i, X&& _a) : i(_i), a(std::forward<X>(_a)) {}                                                  
    
      ...
    };
    
    模板
    B类{
    公众:
    样板
    B(size_t_i,X&&u a):i(_i),a(std::forward(_a)){
    ...
    };
    

    这将生成一个构造函数
    B(size\u t,const char*)
    ,它将完美地匹配
    emplace\u back(5,“Hello”)
    ,只需从
    const char*

    转换为
    a
    ,每个参数允许一个用户定义的转换序列,并且您有两个:

  • const char*
    -->
    std::string
  • std::string
    -->
    C
  • 您可以通过实现通用转发构造函数来减少隐式转换的数量:

    template<typename A>                                                                
    class B {                                                                           
      public:
    
        template<typename X>
        B(size_t _i, X&& _a) : i(_i), a(std::forward<X>(_a)) {}                                                  
    
      ...
    };
    
    模板
    B类{
    公众:
    样板
    B(size_t_i,X&&u a):i(_i),a(std::forward(_a)){
    ...
    };
    

    这将生成一个构造函数
    B(size\u t,const char*)
    ,它将匹配
    emplace\u back(5,“Hello”)
    ,只需从
    const char*

    进行一次转换,就可以完美地构造
    a
    ,但这不起作用的原因并不是因为不能进行隐式转换。在以下代码中:

    vector<B<C>> v;                                                                   
    v.emplace_back(5, "Hello");
    
    为什么这样不行?您经常听到人们说,在调用模板时无法获得隐式转换;这大概是真的。但是
    B
    的构造函数不是模板
    B
    是一个已经模板化的模板类,因此
    B
    是一个普通类,其构造函数不是模板。因此,隐式转换是允许的

    但是,C++中的隐式转换由:

  • 零或一个标准转换序列
  • 零或一个用户定义的转换
  • 零或一个标准转换序列
  • ()

    用户定义的转换基本上是定义隐式构造函数或转换运算符的类
    string
    可能是标准库的一部分,但它只是一个普通类,从
    const char*
    string
    的转换已经算作用户转换。因此,您无法从
    string
    到C获得第二个


    解决此问题的一种方法是为C模板化构造函数,但单参数隐式模板构造函数会让您面临各种其他问题。我可能会定义第二个构造函数,它接受
    常量char*
    。在cppcon,顺便说一句,有一个关于这个问题的完整讨论:。

    这不起作用的原因不是因为不能进行隐式转换。在以下代码中:

    vector<B<C>> v;                                                                   
    v.emplace_back(5, "Hello");
    
    为什么这样不行?您经常听到人们说,在调用模板时无法获得隐式转换;这大概是真的。但是
    B
    的构造函数不是模板
    B
    是一个已经模板化的模板类,因此
    B
    是一个普通类,其构造函数不是模板。因此,隐式转换是允许的

    然而,隐式变换