gpt4 book ai didi

c++ - 隐式构造函数可用于从 Base 派生的所有类型,但当前类型除外?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:24:27 24 4
gpt4 key购买 nike

以下代码总结了我的问题:

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++ 的错误吗?

最佳答案

由于您引用的每个构造函数都是模板化的类方法,因此会调用模板实例化和函数重载解析的规则。

如果您查看 C++11 标准的第 14.8.3 节,第 1-3 段中实际上有一些示例在一定程度上证明了您的问题。基本上,C++ 编译器将在一系列重载模板函数中寻找最佳匹配或“最不通用”的模板函数实例化(必要时添加类型转换)。在您的情况下,因为您已经显式创建了一个构造函数,该构造函数采用 Derived2 的替代实例化。对象,该构造函数将是任何 Derived2<...> 的首选重载类型与采用通用类型的类型相比 T ,甚至是 Base<OtherParameter>争论。

更新:显然,根据 C++11 标准中的 12.3.1/2,

An explicit constructor constructs objects just like non-explicit constructors, but does so only where the direct-initialization syntax (8.5) or where casts (5.2.9, 5.4) are explicitly used.

这意味着如果您不使用直接初始化语法来构造对象或选择强制转换,那么您就不能使用任何标记为 explicit 的构造函数。 .这解释了您在测试 #9 和 #10 之间看到的令人费解的结果。

关于c++ - 隐式构造函数可用于从 Base 派生的所有类型,但当前类型除外?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12185094/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com