Полуобобщенная функция - PullRequest
4 голосов
/ 29 марта 2010

У меня есть куча перегруженных функций, которые работают с определенными типами данных, такими как int, double и strings. Большинство из этих функций выполняют одно и то же действие, где разрешен только определенный набор типов данных. Это означает, что я не могу создать простую универсальную шаблонную функцию, поскольку теряю безопасность типов (и потенциально могу столкнуться с проблемой времени выполнения для проверки внутри функции)

Можно ли создать «полуобобщенную безопасную функцию типа времени компиляции»? Если так, то как? Если нет, то появится ли это в C ++ 0x?

(недействительная) идея;

template <typename T, restrict: int, std::string >
void foo(T bar);
...
foo((int)0); // OK
foo((std::string)"foobar"); // OK
foo((double)0.0); // Compile Error

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

Ответы [ 5 ]

5 голосов
/ 29 марта 2010

Используйте сфину

template<typename> struct restrict { };
template<> struct restrict<string> { typedef void type; };
template<> struct restrict<int> { typedef void type; };

template <typename T>
typename restrict<T>::type foo(T bar);

То, что foo сможет принять только string или int для T. При вызове foo(0.f) ошибка жесткого компиляции не возникает, но вместо этого, если есть другая функция, принимающая аргумент, вместо нее берется одна.

1 голос
/ 29 марта 2010

Вы можете создать «приватную» шаблонизированную функцию, которая никогда не подвергается внешней защите, и вызывать ее из-за ваших «безопасных» перегрузок.

Между прочим, обычно существует проблема с непосредственным представлением шаблонизированной версии: если переданный тип не подходит для этого, будет выдана ошибка компиляции (если вы не знаете, что ваш алгоритм может выявить незначительные ошибки с некоторыми типами данных) .

0 голосов
/ 29 марта 2010

Чтобы перечислить произвольный выбор типов, я полагаю, вы могли бы использовать список типов. Например, см. последнюю часть моего предыдущего ответа .

Использование может быть что-то вроде:

//TODO: enhance typelist declarations to hide the recursiveness
typedef t_list<std::string, t_list<int> > good_for_foo; 

template <class T>
typename boost::enable_if<in_type_list<T, good_for_foo> >::type foo(T t);
0 голосов
/ 29 марта 2010

Возможно, вы могли бы работать со специализациями шаблонов для «ограниченных» типов, которые вы хотите разрешить. Для всех других типов вы не предоставляете специализацию шаблона, поэтому будет использоваться общий «базовый» шаблон. Там вы можете использовать что-то вроде BOOST_STATIC_ASSERT, чтобы выдать ошибку компиляции.

Вот некоторый псевдокод, чтобы прояснить мою идею:

template <typename T>
void foo(T bar) {BOOST_STATIC_ASSERT(FALSE);}

template<> // specialized for double
void foo(double bar) {do_something_useful(bar);};
0 голосов
/ 29 марта 2010

Возможно, немного некрасивое решение, но функторы могут быть вариантом:

class foo {
   void operator()(double); // disable double type
public:
   template<typename T>
   void operator ()(T bar) {
      // do something
   }
};

void test() {
   foo()(3); // compiles
   foo()(2.3); // error
}

Редактировать: я перевернуто мое решение

class foo {
   template<typename T>
   void operator ()(T bar, void* dummy) {
     // do something
   }
public:
   // `int` is allowed
   void operator ()(int i) {
      operator ()(i, 0);
   }
};

foo()(2.3); // unfortunately, compiles
foo()(3); // compiles
foo()("hi"); // error
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...