3

我试图模仿可继承构造函数的行为,因为它们尚未在 g++ 中实现。

我尝试了这里描述的技术https://stackoverflow.com/a/5411992/234261但是当我想添加自己的构造函数时遇到了问题。具体来说,我正在尝试添加一个专门的复制构造函数,以及继承所有其他构造函数。不幸的是,总是调用继承的、更通用的复制构造函数。

一个例子

#include <iostream>
struct A {
  A(){}
  A(const A &){ std::cout << "IN A" << std::endl; }
};

struct B : public A{
  template<typename ...Args,
           typename = typename std::enable_if
      <
             std::is_constructible<A, Args...>::value
             >::type>
  B(Args &&...args)
    : A(std::forward<Args>(args)...) {}

  // These don't work either.                                                                                                                
  //B(const A &a):A(a){ std::cout << "IN B-A" << std::endl; }                                                                                
  //B(const B &b):A(b){ std::cout << "IN B-B" << std::endl; }                                                                                
};
template<>
B::B(const A &a):A(a){ std::cout << "IN B-A" << std::endl; }
template<>
B::B(const B &b):A(b){ std::cout << "IN B-B" << std::endl; }

int main(){
  A a;      // 1. Prints nothing as expected                                                                                                    
  B b(a);   // 2. Prints "IN A" only                                                                                                              
  B b1(b);  // 3. Prints "IN A" only                                                                                                              
  return 0;
}

我想 [3] 打印IN A然后IN BB。不知何故,我设法让 [2] 在我的实际代码中工作,但由于某种原因不能在这个小例子中重复它。

我知道由于子类(B)实际上可以用于构造超类(A),因此正在创建模板构造函数。

但是,为什么我的显式特化没有被调用?我是不是专业不正确?有没有更好的办法?


如果有人想运行它,请链接到此示例http://ideone.com/eUHD5

我正在使用 gcc 4.6

4

2 回答 2

4

以下“作品”:

struct B : public A
{
    template<typename ...Args, typename = typename std::enable_if<std::is_constructible<A, Args...>::value>::type>
    B(Args &&...args) : A(std::forward<Args>(args)...) {}

    B(const A & a) : A(a){ std::cout << "IN B-A" << std::endl; }
    B(const B & b) : A(b){ std::cout << "IN B-B" << std::endl; }
};


int main()
{
    A a;
    B b(a);
    B b1(static_cast<B const &>(b)); 
}

这是旧的模板重载是更好的匹配栗子。请参阅STL 的第 3 课以获得深入的解释。基本上,绑定b到推导模板参数的引用Args... = { B }与身份完全匹配,而将其绑定到B const &需要限定符转换,这是身份转换的严格超集。

通过显式转换为 const-reference,模板构造函数和非模板构造函数现在都完美匹配,但作为非模板是决胜局。

于 2012-08-08T23:38:52.553 回答
2

这无需将事物转换为 const 即可工作:

#include <iostream>
struct A {
  A(){}
  A(const A &){ std::cout << "IN A" << std::endl; }
};

struct B : public A{
  B() = default;

  template<typename A0, typename ...Args,
           typename = typename std::enable_if
      <
             !std::is_same<typename std::decay<A0>::type, A>::value &&
             !std::is_same<typename std::decay<A0>::type, B>::value &&
             std::is_constructible<A, A0, Args...>::value
             >::type>
  B(A0&& a0, Args &&...args)
    : A(std::forward<A0>(a0), std::forward<Args>(args)...) {}

  B(const A &a):A(a){ std::cout << "IN B-A" << std::endl; }                                                                                
  B(const B &b):A(b){ std::cout << "IN B-B" << std::endl; }                                                                                
};

int main(){
  A a;      // 1. Prints nothing as expected                                                                                                    
  B b(a);   // 2. Prints "IN A" only                                                                                                              
  B b1(b);  // 3. Prints "IN A" only                                                                                                              
  return 0;
}

虽然对作者来说更麻烦,但对客户来说更干净。

于 2012-08-08T23:46:01.803 回答