在运行时选择C++通用类型参数是否可行?

10

在C++中,是否有一种方法可以在运行时选择类的通用类型,或者这是编译时的事情?

我想做的事情类似于这样(伪代码):

Generictype type;
if(somveval==1)
    type = Integer;
if(someval==2)
    type = String;

list<type> myList;

在C++中是否可能实现?如果是,怎么做?


4
任何事情都是可能的。但你试图在C++中做的事情并不容易。如果你解释一下为什么要这样做,我们或许能够给你更好的建议。 - Martin York
5个回答

13

这是一个编译时的问题。编译时必须知道模板参数类型。

话虽如此,使用某些模板元编程技术,你可以在编译时选择一个类型,但前提是所有可能的类型都是在编译时已知,并且只有在编译时可以解析选择类型的条件时才能进行选择。

例如,使用部分特化,您可以根据整数在编译时选择类型:

template <typename T>
class Foo
{ };

template <int N>
struct select_type;

template<>
struct select_type<1>
{
    typedef int type;
};

template<>
struct select_type<2>
{
    typedef float type;
};

int main()
{
    Foo<select_type<1>::type> f1; // will give you Foo<int>
    Foo<select_type<2>::type> f2; // will give you Foo<float>
}

2

正如其他人所回答的,你问题的答案是“不”,C ++不支持运行时动态类型。我只想指出,根据你想要实现什么,你可以使用联合模拟这种动态类型,这就是COM中实现的VARIANT类型的方式。


2
使用Boost.Variant(固定数量的不同类型)或Boost.Any(可以存储任何类型的类型,基本上是您的“void指针”,但具有类型信息),可以实现。如果String和Integer恰好是从多态基类派生的,则也可能。 (但是为此,它们必须实现相同的接口,这在您的情况下可能或可能不可能。)通常,多态是最简单的方法,并且确实经常使用。Variant和Any需要相当多的工作才能使用:您仍然需要以正确的类型获取它们存储的内容。(有点像使用向下转换到派生类,而不是依赖于多态方法调用。)

0

我想不出这种情况会有什么用处,但是……

#include "boost/variant.hpp"
#include <list>
#include <string>

boost::variant<std::list<int>, std::list<std::string> >
unknown(int someval) {
    if (someval == 1)
        return boost::variant<std::list<int>, std::list<std::string> >(
                std::list<int>());
    else if (someval == 2)
        return boost::variant<std::list<int>, std::list<std::string> >(
                std::list<std::string>());
}

0

最接近的是:

template <typename T>
void do_stuff_with_list
{
    list<T> myList;
    ...
}

enum Type
{
   Integer = 1,
   String
};

void do_stuff(Type type)
{
    switch (type)
    {
    case Integer:
        do_stuff_with_list<int>();
        break;
    case String:
        do_stuff_with_list<string>();
        break;
    };
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接