Я хотел бы условно включить функции (или, в частности, конструкторы) в зависимости от типа переменной, который я определяю на уровне препроцессора, например

#define my_type double

И в любой момент я могу условно включить функцию

#if my_type == double
void my_fct();
#endif

Который отлично работает. Однако как мне это сделать, если я хочу назначить шаблонный тип для my_type. Например, используя сложное двойное, я бы наивно предположил, что

#if my_type == complex<double>

Будет работать, но препроцессор, кажется, интерпретирует последний ">" как оператор на уровне препроцессора. Я не вижу способа использовать typedefs, так как я хочу, чтобы препроцессор выполнял условное включение. Конечно, я мог бы создать шаблон для всего своего класса и избежать использования препроцессора для этой задачи, но в настоящее время я бы предпочел этого не делать. Кроме того, всегда можно было определить еще один флаг препроцессора в дополнение к типу, но это кажется довольно грязным.

2
ulf 6 Ноя 2014 в 15:39
Вы знаете, вы можете сделать функцию шаблоном, а не целым классом, если хотите.
 – 
icabod
6 Ноя 2014 в 15:45
Я полностью не согласен с тем, что ваше последнее решение «кажется довольно грязным». Используйте typedefs для псевдонимов типов и препроцессор для условного кода.
 – 
molbdnilo
6 Ноя 2014 в 15:47

4 ответа

Лучший ответ

#if my_type == double не проверяет, выполнили ли вы #define my_type double. На самом деле это всегда будет правдой.

В арифметике препроцессора вы можете использовать только целочисленные константные выражения, поэтому вам нужно будет настроить что-то вроде:

// from your makefile or whatever
#define MY_TYPE MY_DOUBLE

...

// in header file
#define MY_INT 3
#define MY_DOUBLE 4
#define MY_COMPLEX_DOUBLE 5

#if MY_TYPE == MY_DOUBLE
    typedef double my_type;
#elif MY_TYPE == MY_INT
    typedef int my_type;
#elif MY_TYPE == MY_COMPLEX_DOUBLE
    typedef complex<double> my_type;
#endif
8
M.M 6 Ноя 2014 в 15:45

Я очень удивлен, что my_type == double работает; это определенно не должно. Препроцессор может вычислять только простые числовые выражения.

Итак, ответ - нет, вы не можете работать с типами шаблонов (препроцессор не знает о типах, он просто выполняет подстановку токенов). Если вам нужна логика на уровне типов, вам нужны шаблоны.

1
Sebastian Redl 6 Ноя 2014 в 15:45
2
Это «работает», потому что буквенно-цифровые токены заменены на 0 для арифметики, поэтому это проверяет, если 0 == 0
 – 
M.M
6 Ноя 2014 в 15:46
Не знал, интересно. Я думаю, это так, что #if MY_FEATURE_DEFINE == 1 работает?
 – 
Sebastian Redl
6 Ноя 2014 в 16:48
Вероятно.. Есть много кода, который использует это (например, #if __cplusplus > 20110101)
 – 
M.M
7 Ноя 2014 в 00:12

А как насчет полноценного шаблона вроде:

template <class T>
void my_fct() {
 // your code based on T as a type
}

И вы называете как: my_fct<int>, my_fct<double> и т. Д. Для передачи типа данных для создания соответствующего шаблона.

0
Dr. Debasish Jana 6 Ноя 2014 в 16:04
Спасибо за предложение. Это действительно сработало бы для нормальной функции, но не в моем случае. Я неправильно сформулировал свой пример: я условно хочу включать разные конструкторы класса в зависимости от типа данных, так как некоторые операции приведения не работают автоматически. Но он должен работать с методом, предложенным выше. Еще раз спасибо!
 – 
ulf
6 Ноя 2014 в 19:31

Идеи, похожие на @ Debasish-Jana: использовать в качестве typtdef и шаблонных функций, выглядит немного некрасиво:

type typedef double my_type;

И функция для случая double:

template<typename T = my_type>
typename std::enable_if<std::is_same<T,double>::value, void>::type 
cnt() 
{

}

И еще один или номера cmplex:

template<typename T = my_type>
typename std::enable_if<std::is_same<T,std::complex<double>>::value, void>::type 
cnt() 
{

}

Пример здесь: https://ideone.com/aXupSa. Попробовав это, я задаюсь вопросом, зачем мне писать такой код. Красиво и красиво - это что-то другое.

0
tgmath 6 Ноя 2014 в 16:16