Можно ли выбрать параметр общего типа C ++ во время выполнения? - PullRequest
7 голосов
/ 15 ноября 2009

Есть ли способ выбрать универсальный тип класса во время выполнения или это время компиляции в C ++?

Я хочу сделать что-то вроде этого (псевдокод):

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

list<type> myList;

Возможно ли это в C ++? и если да, то как?

Ответы [ 5 ]

11 голосов
/ 15 ноября 2009

Это время компиляции. Типы параметров шаблона должны быть известны компилятору во время компиляции.

Это означает, что, используя определенные методы метапрограммирования шаблона, вы можете выбрать тот или иной тип AT во время компиляции, но только если все возможные типы известны во время компиляции, и только если условие для выбора типа может быть решена во время компиляции.

Например, используя частичную специализацию, вы можете выбрать тип во время компиляции на основе целого числа:

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 голосов
/ 15 ноября 2009

Это возможно с Boost.Variant (фиксированное число различных типов) или Boost.Any (тип, который может хранить любой тип, в основном ваш «указатель пустоты», но с информацией о типе).

Также возможно, если String и Integer были получены из полиморфного базового класса. (Но для этого им придется реализовать один и тот же интерфейс, что может или не может быть возможным в вашем случае.)

Как правило, полиморфизм - это самый простой способ сделать это, и он действительно используется постоянно.

Вариант и Любой требует много работы: вам все равно нужно каким-то образом получить содержимое как нужный тип, который они хранят. (Вроде как если бы вы использовали приведения к производным классам вместо того, чтобы полагаться на полиморфные вызовы методов.)

1 голос
/ 15 ноября 2009

Как и другие, ответили на ваш вопрос "Нет", C ++ не поддерживает динамическую типизацию во время выполнения. Я просто хотел отметить, что в зависимости от того, что вы пытаетесь выполнить, вы можете моделировать эту динамическую типизацию, используя union , то есть, как VARIANT тип реализован в COM.

0 голосов
/ 15 ноября 2009

Ближайшее, что вы получите:

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;
    };
}
0 голосов
/ 15 ноября 2009

Я не могу вспомнить ситуацию, когда это было бы полезно, но & hellip;

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