2010-04-22 2 views
3

C# имеет общие типы функций, таких как Action<T> или Func<T,U,V,...>C Действие # стиль <T>, Func <T,T>, и т.д. в C++ 0x

С появлением C++ 0x и возможность иметь шаблон TYPEDEF-х и VARIADIC параметров шаблона , похоже, это должно быть возможно.

Очевидное решение мне было бы это:

template <typename T> 
using Action<T> = void (*)(T); 

однако это не приспосабливает для функторов или C++ 0x лямбды, и кроме того, не компилирует с ошибкой «expected unqualified-id before 'using'»

Моя следующая попытка была, возможно, использовать повышение :: функции:

template <typename T> 
using Action<T> = boost::function<void (T)>; 

Это не компилируется либо, по той же причине.

Моя только другая идея была бы STL аргументы шаблона стиля:

template <typename T, typename Action> 
void foo(T value, Action f) { 
    f(value); 
} 

Но это не дает сильно типизированных решение, и имеет значение только внутри шаблонных функций.

Я сейчас первый, кто признает, что я не C++ wiz, я предпочитаю думать, что я есть, поэтому очень возможно, что есть явное решение, которое я не вижу.

Возможно ли иметь общие типы функций C# в C++?

+0

Нет, это невозможно. Не совсем. Это разные языки. Вопрос в том, что самое близкое приближение, * на основе ваших потребностей *. Вам нужно стирать стили, поэтому каждый функтор с одной и той же подписью выглядит как тот же тип? Если это так, вам придется прыгать через некоторые обручи и терять эффективность. И часто это не стоит, потому что из-за различий между шаблонами и дженериками это часто не * необходимо *. Часто, но не всегда. Что вам нужно, точно? Помимо слепо попытки подражать C# в C++ – jalf

ответ

6

Я думаю, что синтаксис должен быть таким:

template <typename T> 
using Action = void (*)(T); 

Я не мог получить, что для компиляции либо, хотя (г v4.3.2 ++).

Общий шаблон функции стиля STL не строго типизирован в строгом смысле слова, но он безопасен в том смысле, что компилятор гарантирует, что шаблон создается только для типов, удовлетворяющих всем требованиям функции. В частности, это будет ошибка компилятора, если Action не может быть вызван одним параметром типа T. Это очень гибкий подход, поскольку не имеет значения, создается ли функция Action как функция или какой-то класс, который реализует operator().

старый не-C++ 0x обходной путь для недостающего шаблонного ЬурейиХ будет использовать шаблонную-структуру с вложенным ЬурейиМ:

template <typename T> 
struct Action { 
    typedef boost::function<void (T)> type; 
}; 

template <typename T> 
void foo(T value, typename Action<T>::type f) { 
    f(value); 
} 
1

Gcc не поддерживает пока шаблон псевдонимы (см here), и я не уверен, рассматривается ли альтернативный шаблонный псевдоним. Я не думаю, что другие компиляторы уже поддерживают эту функцию.

Я просто использую функцию std :: function или std :: вместо Action или Func.

Конечно, вы можете определить вариационные классы шаблонов Action или Func из std :: function, но я не вижу преимущества.

1

Я не думаю, что общий тип функции является интуитивным C++, потому что шаблоны C++ работают по-разному с дженериками.

Путь C++ - использовать объекты функций - все, что вы можете положить () после, и это имеет смысл для компилятора. Это может быть указатель на функцию, класс с operator() и т. Д. Это работает, потому что шаблоны C++ похожи на модные макросы, и до тех пор, пока код имеет смысл с замененными типами, вы в порядке.

C# generics не работают так - они более ограничительные, вероятно, в попытке улучшить сообщения об ошибках (так как получение шаблонов C++ ошибочно лидирует в выводах). Я не знаю слишком много о C# generics, но я думаю, что они полагаются на что-то, что больше похоже на обратные вызовы, следовательно, полезность функций generics.