Avi*_*Avi 3 c++ templates c++11
我有以下代码:
helper.hpp:
struct A {
uint32_t a, b;
};
struct B {
uint32_t a, b;
};
template <typename T>
struct C {
T barcode;
};
Run Code Online (Sandbox Code Playgroud)
现在基于某些条件我想在main.cpp中创建适当的struct对象
if(/* something */) {
C<A> obj;
}
else {
C<B> obj;
}
Run Code Online (Sandbox Code Playgroud)
现在问题是因为它在if范围内我无法访问它.处理它的一种方法是从函数返回对象,如下所示:
template <typename T>
C<T> getObject(){
if(/* something */) {
return C<A>{};
}
else{
return C<B>{};
}
}
auto obj = getObject()
Run Code Online (Sandbox Code Playgroud)
但这给了我以下编译错误:
错误:没有用于调用'getObject()注释的匹配函数:无法推导出模板参数'T'
真的很感激任何帮助.
C++中的类型是在编译时确定的.这意味着运行时条件不能用于推断对象的类型.
看到你如何使用模板告诉我,这里有一点误解.模板代码由编译器实例化.模板中的代码在实例化之前不是真正的代码.如果我们手动使用该类型对您的代码进行实例化A,它将看起来像这样(不是实际代码):
template <>
auto getObject<A>() -> C<A> {
if(/* something at runtime */) {
return C<A>{};
} else {
return C<B>{};
}
}
// auto
C<A> obj = getObject<A>();
Run Code Online (Sandbox Code Playgroud)
如您所见,else中的代码没有意义.您不能C<B>在必须返回的函数内返回类型的值C<A>.作为代码的编译时间实例的副作用,C<A>并且C<B>是无关的并且是完全不同的类型.
此外,您可以看到auto已被替换为C<A>.这是因为auto在编译时也是推断的.
现在......您可以做些什么来使您的代码工作?
有多个解决方案和抽象来拥有一个具有运行时定义类型的变量.我将介绍一些您可以使用的选项.
变量是一个类,它可以保存变量的单个实例,该变量可以是不同类型,在有限的类型列表中指定.例如,a std::variant<int, std::string>是一个可以是整数或字符串的变量.
在你的代码,这将是一个变种C<A>和C<B>:
auto getObject() -> std::variant<C<A>, C<B>> {
if (/* something at runtime */) {
return C<A>{};
} else {
return C<B>{};
}
}
auto obj = getObject();
// The type of obj is std::variant<C<A>, C<B>>
Run Code Online (Sandbox Code Playgroud)
如果您无法访问C++ 17,则可以随时使用boost::variant.
这个解决方案的缺点是你必须知道变体可以采用的每种类型.如果您有无限数量的类型,则不能使用变体.然而,它非常快并且促进规律性(价值语义).
虚拟多态是获取在运行时决定的不同类型变量的最常用方法.它看起来不错,但是它带有指针和动态分配的价格,并且相当具有侵入性.它看起来像这样:
struct CC {
virtual ~CC() = default;
};
template<typename T>
struct C : CC {
T barcode;
};
auto getObject() -> std::unique_ptr<CC> {
if (/* something at runtime */) {
return std::make_unique<C<A>>();
} else {
return std::make_unique<C<B>>();
}
}
auto obj = getObject();
// The type of obj is std::unique_ptr<CC>
Run Code Online (Sandbox Code Playgroud)
请注意,如果这是您要执行的操作,则必须在其中定义一些通用接口CC.其余的代码将使用该通用接口来执行操作C和条形码.
请注意,这std::make_unique是C++ 14的一部分.它可以分别替换为std::unique_ptr<C<A>>{new C<A>}和std::unique_ptr<C<B>>{new C<B>}.
还有std::any其他形式的类型擦除技术可用.这个答案已经很长了.您可以在线免费找到大量文档,深入介绍所有这些内容.
我仍然想知道是否有任何有用的情况,你会想要这样的东西......但我能想到的唯一方法是何时condition可以在编译时评估,因为这将使编译器能够使用这两个中的任何一个类型。
// 'auto' to let the compiler deduce the correct type at compile time.
auto getObject() {
// those 2 branches are evaluated at compile time only, which lets the compiler
// discard the other branch, making the code valid.
if constexpr(/*something at compile time*/)
return C<A>{};
else
return C<B>{};
}
Run Code Online (Sandbox Code Playgroud)
用法非常简单:
auto obj = getObject();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1824 次 |
| 最近记录: |