mat*_*scy 3 c++ templates variadic-templates parameter-pack
这是我的问题,我有一个基类Base、两个派生类ClassA和仅采用两个参数的ClassB形式Base,以及两个类ClassB0并ClassB1从ClassB采用三个参数派生而来。我想根据传递给函数的类型创建类实例create,如果类型派生自ClassB,则第一个参数将填充为 10。编译器总是警告没有匹配的构造函数。
#include <iostream>
#include <type_traits>
class Base {};
class ClassA : public Base {
public:
ClassA(int a, int b) : Base() {
std::cout << "ClassA: " << a << " " << b << "\n\n";
}
};
class ClassB : public Base {
public:
ClassB(int a, int b, int c) : Base() {
std::cout << "ClassB: " << a << " " << b << " " << c << "\n";
}
};
class ClassB0 : public ClassB {
public:
ClassB0(int a, int b, int c) : ClassB(a, b, c) {
std::cout << "ClassB0: " << a << " " << b << " " << c << "\n\n";
}
};
class ClassB1 : public ClassB {
public:
ClassB1(int a, int b, int c) : ClassB(a, b, c) {
std::cout << "ClassB1: " << a << " " << b << " " << c << "\n\n";
}
};
template <typename T, typename ...Args>
T* create(Args&&... args) {
T* comp = nullptr;
if (std::is_base_of<ClassB, T>::value) {
std::cout << "True ";
comp = new T(10, std::forward<Args>(args)...);
} else {
std::cout << "False ";
comp = new T(std::forward<Args>(args)...);
}
return comp;
}
int main() {
create<ClassA>(1, 2);
create<ClassB0>(2, 3);
create<ClassB1>(2, 3);
}
Run Code Online (Sandbox Code Playgroud)
问题是,双方的分支if,并else需要在编译时进行评估,尽管其中一个会在运行时进行评估。
您可以应用constexpr if 语句(C++17 起),其条件必须在编译时已知,并且iforelse分支将被丢弃并且不会在编译时再次评估。
如果值为
true,则丢弃statement-false(如果存在),否则丢弃statement-true。
template <typename T, typename ...Args>
T* create(Args&&... args) {
T* comp = nullptr;
if constexpr (std::is_base_of<ClassB, T>::value) {
// ^^^^^^^^^
std::cout << "True ";
comp = new T(10, std::forward<Args>(args)...);
} else {
std::cout << "False ";
comp = new T(std::forward<Args>(args)...);
}
return comp;
}
Run Code Online (Sandbox Code Playgroud)
在 C++17 之前,您可以使用SFINAE应用重载。例如
template <typename T, typename ...Args>
typename std::enable_if<std::is_base_of<ClassB, T>::value, T*>::type
create(Args&&... args) {
T* comp = nullptr;
std::cout << "True ";
comp = new T(10, std::forward<Args>(args)...);
return comp;
}
template <typename T, typename ...Args>
typename std::enable_if<!std::is_base_of<ClassB, T>::value, T*>::type
create(Args&&... args) {
T* comp = nullptr;
std::cout << "False ";
comp = new T(std::forward<Args>(args)...);
return comp;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
87 次 |
| 最近记录: |