C++ 模板类构造函数获取模板类的实例

C++ 模板类构造函数获取模板类的实例,c++,templates,C++,Templates,我的情况如下: Class Bar { ... } template <class T> class Foo { public: ... Foo(Foo<Bar> bar) { ... } ... } 类栏{ ... } 模板 福班{ 公众: ... 富(富吧){ ... } ... } 因此,类Foo的构造函数之一可以接受由Bar参数化的类Foo的元素。这一切都很好,直到我实例化了一些由Bar参数化的Foo类,其中这个构造函数被解释为一个复

我的情况如下:

Class Bar {
...
}

template <class T>
class Foo {
public:
  ...
  Foo(Foo<Bar> bar) {
    ...
  }
  ...
}
类栏{
...
}
模板
福班{
公众:
...
富(富吧){
...
}
...
}
因此,类Foo的构造函数之一可以接受由Bar参数化的类Foo的元素。这一切都很好,直到我实例化了一些由Bar参数化的Foo类,其中这个构造函数被解释为一个复制构造函数,这不是我想要的。我想知道如何让构造函数在不干扰复制构造函数的情况下获取这样的元素。例如,我可以这样做:

template <class T>
class Foo {
public:
  ...
  Foo(Foo<Bar> bar, int unused) {
    ...
  }
  ...
}
template<typename U>
Foo(U bar, typename boost::enable_if<boost::is_same<U, Foo<Bar> > >::type* = 0);
模板
福班{
公众:
...
Foo(Foo-bar,int未使用){
...
}
...
}

它工作得很好,因为现在构造函数与复制构造函数不冲突。有没有标准的方法来处理这个问题?

这实际上不是一个有效的复制构造函数,因为复制构造函数应该遵循以下四种格式之一:

MyClass( const MyClass& other );
MyClass( MyClass& other );
MyClass( volatile const MyClass& other );
MyClass( volatile MyClass& other );
为了使一切按预期工作,请将参数作为指针传递:

Foo(Foo<Bar>* bar) {
    // Logic
}
Foo(Foo*bar){
//逻辑
}

如果按值传递,则如果逻辑模拟复制构造函数,则可以很好地创建一个无限循环。

如果类模板不需要声明复制构造函数(在一般情况下),则可以将构造函数声明为

Foo(Foo<Bar> const& bar);
Foo(Foo const&bar);
它通常是转换构造函数和
Foo
的副本构造函数。在适用的情况下,其他专门化将使用隐式声明的复制构造函数

否则,将构造函数作为模板可确保它不是特殊成员。也就是说,必须注意该构造函数不要干扰复制构造函数。这不好,但你可以这样做:

template <class T>
class Foo {
public:
  ...
  Foo(Foo<Bar> bar, int unused) {
    ...
  }
  ...
}
template<typename U>
Foo(U bar, typename boost::enable_if<boost::is_same<U, Foo<Bar> > >::type* = 0);
模板
Foo(ubar,typename boost::enable_if::type*=0);
这是一个不是复制构造函数的构造函数,仅在传递类型为
Foo
的参数时使用。请注意,由于重载解析的规则,
Foo
的复制构造函数将优先于此构造函数


前面是针对C++03的。下面是一个简单的C++11解决方案:

template<int = 0>
Foo(Foo<Bar>);
模板
富(富),;

C++11解决方案有效吗?这(我相信)可以很容易地用C++11以一种干净的方式解决,但你必须求助于C++03中的黑客技术。为什么这很重要?你遇到了什么副作用?@Wug:对于初学者来说,你不能有一个按值获取参数的复制构造函数,因此它将无法编译。你能通过传递指针来解决它吗?你是否尝试使构造函数显式化?这个解决方案可以工作,但实际上相当于我的int unused解决方案。我想我未使用的int更安全,不会阻止像这样的编译器优化。@dschatz毕竟你是在要求一个替代方案。如果你更喜欢你的解决方案而不是替代方案,你绝对应该使用它。你能解释一下c++11解决方案吗?我没有访问Boost的权限,但c++11在我的环境中是公平的。@dschatz:模板构造函数永远不是复制构造函数。添加未使用的模板参数会使此特定构造函数不是模板。Luc,这真的有效吗(即调用站点的语法没有改变吗?这可以用作隐式转换吗?)我打算在
template Foo(Foo)
(即在默认参数上使用SFINAE)@dschatz中提出一些建议。构造函数是一个模板,因此它永远不会被认为是一个复制构造函数。这意味着,即使为
Foo
专门化实例化,也可以声明它采用
Foo
。此外,对于
Foo
而言,由于重载解析规则,复制或移动构造函数将优先于该构造函数(适用时,非模板优于模板)@DavidRodríguez dribeas这取决于这样一个事实:当涉及到重载解析时,最终使用默认值的模板参数与推断参数一样好。事实上,查找模板参数的整个过程都是在重载解析之前进行的。@dschatz在C++03中不允许对函数模板使用默认模板参数。(但是类模板是)问题的关键是
Foo(Foo)Foo
专门化的情况下,code>声明了一个复制构造函数,这些构造函数不允许按值获取参数(另外,如果您在其他地方声明/定义了一个复制构造函数,这是另一个问题)。不能为
Foo
专门化调用此构造函数是重载解析的产物,实际上与技巧无关。