Определить тип аргумента - PullRequest
       3

Определить тип аргумента

0 голосов
/ 17 февраля 2011

Можно ли как-то отразить тип аргумента функции во время компиляции?

Так что

int b = add(3, 6)

приведет к созданию экземпляра шаблона в виде

int add(int a, int b) { return a + b }

из некоторого, однако, объявленного шаблона функции

A add(A a, B b) { return a + b }

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

Ответы [ 5 ]

3 голосов
/ 17 февраля 2011

Разве это не делает то, что вы просите?

template <typename A, typename B>
A add(A a, B b) { return a + b; }

Это вряд ли "тяжелое метапрограммирование".

3 голосов
/ 17 февраля 2011
template<typename T>
T add(T a, T b) { return a + b; }

Затем вы можете вызывать это с любым встроенным типом (int, short, double, float и т. Д.), И он будет создавать функцию add во время компиляции в соответствии с типом, который вы используете.

Обратите внимание, что если вы разделите это на заголовок / источник, у вас будут проблемы:

add.h:

template<typename T>
T add(T a, T b);

add.cpp:

template<typename T>
T add(T a, T b) { return a + b; }

main.cpp:

#include "add.h"

int a = 3;
int b = 5;
int i = add(a, b);

Когда вы попытаетесь скомпилировать это, он потерпит неудачу во время соединения.Вот почему.

Компиляция add.obj делает не экземпляром шаблона add, поскольку он никогда не вызывается в add.cpp.Компиляция main.obj создает объявление функции, но не тело функции.Поэтому во время компоновки не удастся найти определение метода add.

Самое простое решение - просто поместить всю функцию шаблона в заголовок:

add.h:

template<typename T>
T add(T a, T b) { return a + b; }

и тогда вам даже не нужен файл add.cpp.

1 голос
/ 17 февраля 2011

Если вы планируете использовать что-либо, кроме простых типов, которые вы хотите (в заголовочном файле):

template <typename A>
inline A add(const A& a, const A& b) { return a + b; }

Обратите внимание на «inline».

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

шаблон inline A add (A a, B b) {вернуть a + b; }

Тогда это терпит неудачу (вероятно, только с предупреждением):

double d = add(1, 1.5); // Sets d to 2.0

Так что вам нужно поработать. Например:

template<class A, class B>
struct Promote
{
};

template<class A>
struct Promote<A,A>
{
    typedef  A Type;
};

template<>
struct Promote<int, double>
{
    typedef double Type;
};

template<>
struct Promote<double, int>
{
    typedef double Type;
};

Функция добавления становится:

template<class A, class B>
inline typename Promote<A,B>::Type add(A a, B b)
{
    return a + b;
}

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

1 голос
/ 17 февраля 2011

Это именно то, что делают шаблоны.

template <typename T>
inline T add(T a, T b) { return a + b; }

Разрешение двух разных типов немного сложнее, но также возможно.

0 голосов
/ 17 февраля 2011

Шаблоны делают всю свою магию во время компиляции, но этого вполне достаточно для того, что вы просите:

template <class T>
T add(T a, T b) {  return a + b; }

Это становится немного сложнее, когда эти два значения могут не совпадать, поэтому (например) вы можете добавить int к double и получить результат double. Текущий стандарт на самом деле не поддерживает это 1 ; в C ++ 0x вы можете посмотреть auto и decltype для таких задач.

1 Хотя Boost typeof будет часто выполнять эту работу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...