【发布时间】:2012-08-24 11:39:47
【问题描述】:
以下代码总结了我的问题:
template<class Parameter>
class Base {};
template<class Parameter1, class Parameter2, class Parameter>
class Derived1 : public Base<Parameter>
{ };
template<class Parameter1, class Parameter2, class Parameter>
class Derived2 : public Base<Parameter>
{
public :
// Copy constructor
Derived2(const Derived2& x);
// An EXPLICIT constructor that does a special conversion for a Derived2
// with other template parameters
template<class OtherParameter1, class OtherParameter2, class OtherParameter>
explicit Derived2(
const Derived2<OtherParameter1, OtherParameter2, OtherParameter>& x
);
// Now the problem : I want an IMPLICIT constructor that will work for every
// type derived from Base EXCEPT
// Derived2<OtherParameter1, OtherParameter2, OtherParameter>
template<class Type, class = typename std::enable_if</* SOMETHING */>::type>
Derived2(const Type& x);
};
考虑到我已经有示例代码中的显式构造函数,如何将隐式构造函数限制为从父类派生的所有类(当前类除外),无论其模板参数是什么?
编辑: 对于 Base 的隐式构造函数,我显然可以这样写:
template<class OtherParameter> Derived2(const Base<OtherParameter>& x);
但是在那种情况下,我是否可以保证编译器不会将此构造函数用作Derived2<OtherParameter1, OtherParameter2, OtherParameter> 的隐式构造函数?
编辑2: 在这里我有一个测试:(LWS在这里:http://liveworkspace.org/code/cd423fb44fb4c97bc3b843732d837abc)
#include <iostream>
template<typename Type> class Base {};
template<typename Type> class Other : public Base<Type> {};
template<typename Type> class Derived : public Base<Type>
{
public:
Derived() {std::cout<<"empty"<<std::endl;}
Derived(const Derived<Type>& x) {std::cout<<"copy"<<std::endl;}
template<typename OtherType> explicit Derived(const Derived<OtherType>& x) {std::cout<<"explicit"<<std::endl;}
template<typename OtherType> Derived(const Base<OtherType>& x) {std::cout<<"implicit"<<std::endl;}
};
int main()
{
Other<int> other0;
Other<double> other1;
std::cout<<"1 = ";
Derived<int> dint1; // <- empty
std::cout<<"2 = ";
Derived<int> dint2; // <- empty
std::cout<<"3 = ";
Derived<double> ddouble; // <- empty
std::cout<<"4 = ";
Derived<double> ddouble1(ddouble); // <- copy
std::cout<<"5 = ";
Derived<double> ddouble2(dint1); // <- explicit
std::cout<<"6 = ";
ddouble = other0; // <- implicit
std::cout<<"7 = ";
ddouble = other1; // <- implicit
std::cout<<"8 = ";
ddouble = ddouble2; // <- nothing (normal : default assignment)
std::cout<<"\n9 = ";
ddouble = Derived<double>(dint1); // <- explicit
std::cout<<"10 = ";
ddouble = dint2; // <- implicit : WHY ?!?!
return 0;
}
最后一行让我担心。 C++标准可以吗?是g++的bug吗?
【问题讨论】:
-
为什么使用
Derived2<OtherParameter1, OtherParameter2, OtherParameter>参数调用的构造函数更喜欢隐式构造函数而不是explicit构造函数,因为隐式构造函数的模板实例化比explicit构造函数更通用? -
当前类和 // Derived2
可以不同... -
如果我为隐式构造函数写:
template<class Other> Derived2(const Base<Other>& x)我是否有保证Derived2<OtherParameter1, OtherParameter2, OtherParameter>永远不会被隐式转换? -
是的,当然它们可以(或通常会)不同,但与一般类型
T相比,Derived2<...>实例不会更好地匹配Derived2<...>参数吗? C++ 编译器不是为实例化寻找最不通用的模板吗? -
@ForEveR:使用
explicit构造函数,我认为它更像这样:liveworkspace.org/code/e48a3b5f1e670f785e68db4e67739b44
标签: c++ c++11 implicit-conversion enable-if explicit-constructor