【问题标题】:Is it possible to choose a C++ generic type parameter at runtime?是否可以在运行时选择 C++ 泛型类型参数?
【发布时间】:2010-12-16 16:29:27
【问题描述】:

有没有办法在运行时选择类的泛型类型,还是在 C++ 中这是编译时的事情?

我想做的是这样的(伪代码):

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

list<type> myList;

这在 C++ 中可行吗?如果是,如何?

【问题讨论】:

  • 一切皆有可能。但是你想要做的事情在 C++ 中并不容易。如果您解释为什么要这样做,我们也许可以给您更好的建议。

标签: c++ dynamic templates types generics


【解决方案1】:

这是编译时的事情。模板参数类型必须在编译时为编译器所知。

也就是说,使用某些模板元编程技术,您可以在编译时选择一种或另一种类型,但前提是所有可能的类型在编译时都已知,并且只有选择类型的条件可以在编译时解决。

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

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++ 不支持运行时的动态类型。我只是想指出,根据您要完成的工作,您可以使用 union 模拟这种动态类型,这就是 @987654321 @ 在 COM 中实现。

    【讨论】:

      【解决方案3】:

      Boost.Variant(固定数量的不同类型)或 Boost.Any(一种可以存储任何类型的类型,基本上是您的“空指针”但带有类型信息)是可能的。

      如果 String 和 Integer 恰好派生自多态基类也是可能的。 (但为此,他们必须实现相同的接口,这在您的情况下可能可行,也可能不可行。)

      一般来说,多态是最简单的方法,而且确实一直在使用。

      Variant 和 Any 需要做很多工作才能使用:您仍然需要以某种方式获取内容作为它们存储的正确类型。 (有点好像你要使用向下转换到派生类,而不是依赖多态方法调用。)

      【讨论】:

        【解决方案4】:

        我想不出这会有用的情况,但是……

        #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>());
        }
        

        【讨论】:

          【解决方案5】:

          你会得到最接近的是:

          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;
              };
          }
          

          【讨论】:

            猜你喜欢
            • 2011-08-18
            • 2012-12-10
            • 1970-01-01
            • 1970-01-01
            • 2016-05-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-07-27
            相关资源
            最近更新 更多