Jar*_*xle 5 c++ templates visual-studio-2010 c++11 inherited-constructors
这是类foo:
template <typename T>
struct foo
{
foo()
{
t = nullptr;
}
foo(T* p, bool flag)
{
t = p;
}
private:
T* t;
};
Run Code Online (Sandbox Code Playgroud)
这是班级栏:
template <typename T>
struct bar: public foo<T>
{
using foo<T>::foo<T>;
};
Run Code Online (Sandbox Code Playgroud)
它是继承构造函数的正确语法吗?如果我使用"使用foo :: foo;" 那么Visual C++ 2010的编译器就死了.那么基本上如何从VC++ 2010中的模板类继承构造函数呢?
template <typename T>
struct bar: public foo<T>
{
using foo<T>::foo<T>;
};
Run Code Online (Sandbox Code Playgroud)
为了让这个解析正确,你需要在template之前插入foo<T>;,告诉编译器foo将被视为模板名称(它不能调查foo<T>告诉自己,因为T是未知的).但是::template在使用声明中不允许使用.该名称也未引用所有构造函数bar:相反,它将引用T此类构造函数的特定构造函数函数模板特化(是模板参数),如下所示
template<typename T>
foo();
Run Code Online (Sandbox Code Playgroud)
另外,对于using声明使用template-id(like foo<T>)作为其名称是无效的(实际上禁止它引用函数模板特化,并且还添加了对名称转换函数模板特化的禁止),所以即使你使用::template(如果可能的话)纠正解析问题,你仍然会在这一点上出错.
当引入继承的构造函数时,添加了允许使用语法规则引用构造函数的特殊规则:如果您具有qualified-id(基本上使用限定名称...::...),并且最后一个部分命名为特定类之前的最后限定,那么你可以用另外两种方式表示该类的构造函数:
foo<T>),并最后部分模板名称匹配(所以,foo<T>::foo或TTP<T>::TTP用TTP作为一个模板的模板参数).foo::foo或者T::T,与T作为一个模板参数).这两个附加规则仅在使用声明中有效.它们自然不存在于C++ 03中.C++ 03中也存在的另一个规则是:如果最后一部分命名了注入的类名,那么这个限定名也引用了构造函数:
foo::foo为此工作.但仅凭这个规则,T::T(where T表示类foo)将无法工作,因为foo没有成员调用T.因此,根据特殊规则,您可以编写
using foo<T>::foo;
using bar::foo::foo; // valid too
Run Code Online (Sandbox Code Playgroud)
第二个也是有效的:foo注入的类名是注入基类foo<T>并继承的bar.我们通过引用该名称bar::foo,然后添加最后一部分foo,它再次引用注入的类名,来表示`foo的构造函数.
现在您了解为什么您尝试的初始名称将引用构造函数函数模板特化(如果允许):因为该foo<T>::foo部件将命名所有构造函数,<T>然后接下来将过滤掉模板并传递类型论点.
如果您的编译器还不支持继承构造函数,但支持可变参数宏,可变参数模板和右值引用,以及非常方便的type_trait,这里有一个非常好的解决方法:
#include <type_traits>
#include <utility>
#include <ostream>
enum Color {Red, Blue};
#define USING(Derived, Base) \
template<typename ...Args, \
typename = typename std::enable_if \
< \
std::is_constructible<Base, Args...>::value \
>::type> \
Derived(Args &&...args) \
: Base(std::forward<Args>(args)...) { } \
template<typename Mixin>
class add_color
: public Mixin
{
Color color;
public:
USING(add_color, Mixin);
friend std::ostream& operator<<(std::ostream& os, const add_color& x)
{
switch (x.color)
{
case Red:
os << "Red";
break;
case Blue:
os << "Blue";
break;
}
os << ' ' << x.first << ' ' << x.second;
return os;
}
};
#include <string>
#include <iostream>
int main()
{
add_color<std::pair<std::string, int>> x1("five", 5);
std::cout << "x1 = " << x1 << '\n';
add_color<std::pair<std::string, int>> x3;
std::cout << "x3 = " << x3 << '\n';
add_color<std::pair<std::string, int>> x4 = x1;
std::cout << "x4 = " << x4 << '\n';
std::pair<std::string, int> p;
add_color<std::pair<std::string, int>> x5 = p;
std::cout << "x5 = " << x5 << '\n';
}
Run Code Online (Sandbox Code Playgroud)
如果你还没有is_constructible,基本的想法在没有它的情况下工作,但是"继承的构造函数"将过于贪婪.
| 归档时间: |
|
| 查看次数: |
2923 次 |
| 最近记录: |