Вопрос по templates, c++, operator-overloading – Шаблон функции с оператором

31

В C ++, вы можете иметь шаблонный оператор в классе? Вот так:

class MyClass {
public:
    template<class T>
    T operator()() { /* return some T */ };
}

Это на самом деле, кажется, компилируется просто отлично, но возникает путаница, как его использовать:

MyClass c;
int i = c<int>(); // This doesn't work
int i = (int)c(); // Neither does this*

Тот факт, что он компилируется, наводит на мысль, что это выполнимо, я просто не знаю, как его использовать! Любые предложения, или этот метод использования не стартер?

Ах, нашел это:stackoverflow.com/questions/942170/… GManNickG
Что это значит "это не работает / не работает"? Что просходит? Jim Buck
Благодарю. Думаю, я просто нажимал не те ключевые слова, когда пытался искать. (Не подумал попробовать функтор. Это должно было быть очевидно в ретроспективе) Toji
Клянусь, я уже видел этот вопрос на SO раньше ... Я не могу его найти, поэтому, очевидно, никто не может винить вас. GManNickG
Компилятор надрывается на вас, вот что происходит :) Toji

Ваш Ответ

3   ответа
18

Вы в основном правы. Допустимо определять шаблонные операторы, но их нельзя вызывать напрямую с явными аргументами шаблона.

Если у вас есть этот оператор:

template <typename T>
T operator()();

как в вашем примере, он может быть вызван только так:

int i = c.operator()<int>();

Конечно, если аргумент шаблона может быть выведен из аргументов, вы все равно можете назвать его обычным способом:

template <typename T>
T operator()(T value);

c(42); // would call operator()<int>

Альтернативой может быть сделать аргумент ссылкой и сохранить вывод вместо того, чтобы возвращать его:

template <typename T>
void operator()(T& value);

Итак, вместо этого:

int r = c.operator()<int>();

ты мог бы сделать

int r;
c(r);

Или, возможно, вы должны просто определить простойget<T>() функция вместо использования оператора.

43

Вам необходимо указатьT.

int i = c.operator()<int>();

К сожалению, в этом случае вы не можете напрямую использовать синтаксис вызова функции.

Изменить: О, и вы пропали без вестиpublic: в начале определения класса.

Да, вам, вероятно, лучше определитьget метод вместоoperator(), Тогда вы могли бы написатьc.get<int>().
На самом деле существует идиома, которая используется многими: функция free get (использование кортежей)get<N>(some_tuple), boost.variant используетget<T>(some_variant)). Так что ваш будет выглядетьget<T>(c), сget определяется вMyClassпространство имен).
В этом случае мне понадобился и вызов, который вернул значение, и вызов, который не сделал. Я реализовалEvaluate<type>() за возвращающуюся версию иExecute() для невозврата, а затем позволил пользователю вызывать оператор () в качестве альтернативы Evaluate. (Имена имеют смысл в контексте, поскольку они выполняют функции, определенные в скрипте.) Так что, по сути, я реализовал функцию get :) Спасибо за все предложения! Toji
Ницца. Слава на быстрый и точный ответ! К сожалению, это, вероятно, является многословным для моего использования (поскольку мой код предназначен для вызова другими, я хочу избежать путаницы), поэтому мне просто нужно найти другой маршрут. Еще раз спасибо! Toji
4

Вы не думаете о

class Foo {
    public:
    template<typename T>
    operator T() const { return T(42); }
};

Foo foo;

int i = (int) foo; // less evil: static_cast<int>(foo);

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

@ kim366: Поскольку это не имеет смысла, думать об этом довольно бессмысленно. Это не должно работать, и это не работает.
Работает в этом случае, но я думал оc<int>++, Я имею в виду, что это не должно работать, и я немного злоупотребляю нотацией там ...
Да, я знаю об этом .. Выглядит круто, хотя: P

Похожие вопросы