如何更改下面的代码以允许使用模板化构造函数创建 Base 对象?
struct Base {
template <typename T>
Base(int a) {}
};
int main(int argc, char const *argv[])
{
Base *b = new Base<char>(2);
delete b;
return 0;
}
Run Code Online (Sandbox Code Playgroud) 假设我正在编写Derived并且必须继承Base,我无法控制并且有两个单独的构造函数和一个已删除的副本和移动构造函数:
struct Base {
Base(int i);
Base(const char *sz);
Base(const Base&) = delete;
Base(const Base&&) = delete;
};
struct Derived {
Derived(bool init_with_string);
};
Run Code Online (Sandbox Code Playgroud)
现在,根据another_param我必须使用构造函数或其他函数初始化我的基类的值; 如果C++不那么严格,那就像是:
Derived::Derived(bool init_with_string) {
if(init_with_string) {
Base::Base("forty-two");
} else {
Base::Base(42);
}
}
Run Code Online (Sandbox Code Playgroud)
(这对于计算值以直接表达式传递给基类构造函数/字段初始化器很麻烦的所有情况也很有用,但我很讨厌)
不幸的是,即使我没有看到特定的codegen或对象模型障碍这种事情,这不是有效的C++,我想不出简单的解决方法.
有什么方法我不知道吗?
我有以下类定义:
class image {
public:
template <class T> image(int w, int h);
virtual ~image();
void clear();
};
template <class T> image::image(int w, int h) {
...
...
}
Run Code Online (Sandbox Code Playgroud)
构造函数在同一个头文件中定义.现在,我如何实例化这个类的对象?
我试过这个
image a<float>(128, 128);
Run Code Online (Sandbox Code Playgroud)
但得到以下错误
error: expected initializer before '<' token
image a<float>(128, 128);
Run Code Online (Sandbox Code Playgroud)
我该怎么做呢?
根据标准,阶级析构函数是否具有迂腐意义上的名称?
回想一下,构造函数显然没有名称:
构造函数没有名称.使用可选的函数说明符序列(7.1.2)后跟构造函数的类名后跟参数列表的特殊声明符语法用于声明或定义构造函数.在这样的声明中,忽略构造函数类名称周围的可选括号.
标准没有明确声明析构函数有或没有名称,但是有许多引用如何使用特殊语言引用和声明析构函数,其中没有一个直接引用析构函数的名称.这个问题似乎在各个地方绕过:
使用可选函数说明符(7.1.2)后跟〜后跟析构函数的类名后跟空参数列表的特殊声明符语法用于在类定义中声明析构函数.
在点之后使用伪析构函数名称.或箭头 - >运算符表示由type-name命名的非类类型的析构函数.结果只能用作函数调用operator()的操作数,并且这种调用的结果类型为void.唯一的效果是在点或箭头之前评估后缀表达式.
在显式析构函数调用中,析构函数名称显示为〜后跟一个命名析构函数类类型的类型名称.析构函数的调用遵循成员函数的通常规则(9.3),也就是说,如果对象不是析构函数的类类型而不是从析构函数的类类型派生的类,则程序具有未定义的行为(除了在空指针上调用delete没有效果).
最后一种情况(12.4.12)似乎是对析构函数名称的最直接引用,但它仍然避免说析构函数有一个名称,并且对此非常暧昧.12.4.12可以解释为"blah是析构函数的名称"或"析构函数没有名称,但你可以将析构函数称为blah".
那么,析构函数是否有名字?
如果类也是模板,是否可以使用模板参数调用构造函数?
#include <stdio.h>
#include <iostream>
template <class A>
struct Class
{
template <class B>
Class(B arg) { std::cout << arg << std::endl; }
};
int main()
{
Class<int> c<float>(1.0f);
Class<int>* ptr = new Class<int><float>(2.0f);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编辑:所以我想调用特定模板构造函数的唯一方法是使用casted paramterers调用它到你想要的模板类型:
#include <stdio.h>
#include <iostream>
template <class A>
struct Class
{
template <class B>
Class(B arg) { std::cout << arg << std::endl; }
Class(double arg) { std::cout << "double" << std::endl; }
Class(float arg) { std::cout << "float" << std::endl; }
}; …Run Code Online (Sandbox Code Playgroud) 我不知道使用SFINAE进行方法重载必须考虑哪些规则.我在问题中多次运行,因为据我所知,接缝更多涉及规则.所以我希望有一套规则可以简单解释,以帮助解决一般问题,而不是一次又一次地提问.
我的起点在这里: 如果需要参数包,请使用SFINAE专门课程
代码1
class AA { public: using TRAIT = int; };
class BB { public: using TRAIT = float; };
template < typename T>
class Y
{
public:
template <typename U = T, typename V= typename std::enable_if< std::is_same< int, typename U::TRAIT>::value, int >::type>
Y( ) { std::cout << "First" << std::endl; }
template <typename U = T, typename V= typename std::enable_if< !std::is_same< int, typename U::TRAIT>::value, float >::type>
Y( ) { std::cout << "Second" << std::endl; }
};
Run Code Online (Sandbox Code Playgroud)
错误:'模板模板Y …
我有一个带有构造函数的模板类std::vector<T>.对于除了一个之外的每个对象,我都希望它进行操作A.但对于那个对象,我希望它做一些其他的东西B.
是否有可能仅为模板类创建显式实例化的构造函数?我希望它的描述足够精确.
问候
更新:我现在已经实现了一个测试用例:
//header
Container(const std::vector<T>& source)
{...}
//source code
template <> Container<int>::Container(const std::vector<int>& source)
{
throw 42;
}
Run Code Online (Sandbox Code Playgroud)
此示例编译但不起作用.我将它导出到一个DLL,并希望每当我尝试使用泛型参数int创建类的实例时调用它.但就像现在一样,它只调用用于每个其他对象的标准构造函数.我必须对声明做出改变吗?
更新:我成功了!只需将其复制到头文件即可.
更新:好的,现在我有另一个问题.我能够为"简单"类型而不是模板进行专门化.我这样试过:
template<typename T>
Container<MyClass<T>>::Container(const std::vecror<MyClass<T>>& source)
{...}
Run Code Online (Sandbox Code Playgroud)
我想为每个MyClass对象专门化它,但MyClass本身应该能够作为模板存在.