我是新手使用模板,我想创建一个返回泛型类型的函数。我做了一个非常简单的模板
enum tag { SHORT, INT, FLOAT, DOUBLE };
template <typename T>
T get_val(tag t){
switch (t) {
case SHORT: return .. //returns a short;
case INT: return .. //returns a int;
case FLOAT: return .. //returns a float;
case DOUBLE: return .. //returns a double;
}
}
问题是浮点数和双精度数以整数形式返回。所以我想知道为什么会发生这种情况,如果有办法我可以正确使用它。
答案 0 :(得分:4)
您不能使用switch
这样的语句来使用不同的返回类型。
但是,如果在编译时知道get_val
的输入,则可以使用模板元编程技术来获得所需的内容。
enum tag { SHORT, INT, FLOAT, DOUBLE };
template <tag t> struct return_type_chooser;
template <> struct return_type_chooser<SHORT>
{
using type = short;
};
template <> struct return_type_chooser<INT>
{
using type = int;
};
template <> struct return_type_chooser<FLOAT>
{
using type = float;
};
template <> struct return_type_chooser<DOUBLE>
{
using type = double;
};
template <tag t>
typename return_type_chooser<T>::type get_val()
{
...
}
您可以使用:
get_val<SHORT>()
但不是
get_val(SHORT)
更新,以回应OP的评论
如果仅在运行时知道get_val
的输入,则std::any
(C++17)或boost::any
应作为返回类型。
答案 1 :(得分:2)
我建议使用变量和运行时检查有限类型的可能类型中的类型:
使用带有枚举的变体的公共接口以获得正确的类型(这是一个天真的版本,您应该使用std::variant
和get_if
):
enum variant_type
{
variant_null,
variant_int,
variant_float,
variant_double,
}
class variant
{
public:
// Add constructors with the correct type for the
// underlying storage
variant() = default;
variant(int x);
variant(float x);
variant(double x);
// ensure you can check for empty variants and check the type
explicit operator int() const;
explicit operator float() const;
explicit operator double() const;
explicit operator bool() const;
variant_type type() const;
private:
variant_type type_ = variant_null;
void* data_ = nullptr;
};
然后,添加许多自定义函数或方法重载,允许您在运行时选择正确的方法:
class my_handler
{
public:
my_handler(const variant& v)
{
switch (v.type()) {
case variant_null;
open(nullptr); break;
case variant_int;
open(int(v)); break;
case variant_float;
open(float(v)); break;
case variant_double;
open(double(v)); break;
}
}
private:
void open(std::nullptr_t nullp);
void open(int x);
void open(float x);
void open(double x);
};
这允许您拥有一个通用的公共接口,用于有限的类型子集,但这样可以避免在编译时知道正确的类型。
使用std::variant
和get_if
可以更加惯用,而不是编写自己的自定义变体类。我这只是一个(低效)示例,说明有多少库(如Windows API和Qt)已经实现了自己的库。