Вопрос: Есть ли способ обнаружить портативно, что стандартный заголовок включен с использованием макросов?


Я хочу сделать эквивалент boost::swap и в моей среде стандартные заголовки могут или не могут быть включены. В зависимости от лицензирования проекта и других вещей.
Я хотел бы сделать части кода, защищенные охранными детекторами:

Рассмотрим один блок компиляции.
конкретный проект, вышеупомянутый потенциал включает:

#include <algorithm> // (or <utility> for C++11 projects)

позже в код проекта, включенный в мой заголовок утилиты swap:

namespace MyCompany
{
  template<class T1, class T2>
  void swap(T1& left, T2& right)
  {
     #ifdef _ALGORITHM_   // you get the idea.
       std::swap(left, right);
     #else
       // fallback impl
     #endif
  }
}

Я упрощен, потому что мы не говорим о деталях трюка ADL здесь, но он будет включен.
здесь для ссылки на то, о чем я говорю, но это не имеет отношения к этому вопросу:
http://www.boost.org/doc/libs/1_57_0/boost/core/swap.hpp

Итак, этот вопрос касается того, как я могу определить стандартное включение заголовка  ? _ALGORITHM_ охранник присутствует в визуальной студии, снабженной заголовком, но я нигде не читаю http://www.cplusplus.com/reference/algorithm/  что он должен иметь любой макрос, который я могу проверить.

( окончательная записка : этот вопрос немного XY предвзято. Я действительно хочу обнаружить присутствие std::swap а не заголовок.)


8


источник


Ответы:


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

#if 0
#include <algorithm>
using std::swap;
#endif

template <typename T>
struct ForceLessSpecialized {
  typedef T TYPE;
};

template <typename T>
void swap (T &, typename ForceLessSpecialized<T>::TYPE &) {
}

void bar () {
  int i;
  swap (i, i);
}  

Что происходит:

Когда есть две специализированные функции шаблона-кандидата, компилятор выполняет «Частичное упорядочение шаблонов функций» ('03 14.5.5.2). Это проверяет, могут ли параметры шаблона функции одного шаблона использоваться для специализации другого.

Для каждого шаблона мы будем использовать фиктивные параметры T1 а также T2 и мы создаем списки фиктивных аргументов, используя эти типы:

// std::swap argument list
( T1 &  , T1 & )

// our swap argument list
( T2 &, typename ForceLessSpecialized<T2>::TYPE & )

Специализируясь на нашем свопе, используя фиктивные аргументы из std::swap дает:

Deduction from First parameter:  T == T1
Deduction from Second parameter:  Non Deduced Context

Выведенное T является T1 и вычет преуспел.

специализация std::swap используя фиктивные аргументы для нашего свопа, дает:

Deduction from First parameter:  T == T2
Deduction from Second parameter:  T == ForceLessSpecialized<T2>::TYPE

Выведенные типы для T не то же самое, и поэтому это считается дедукционным провалом.

Поэтому синтезированные аргументы std::swap могут использоваться для специализации нашего шаблона, но синтезированные аргументы нашего шаблона не могут использоваться для специализации std::swap, std::swap рассматривается как более специализированный, и поэтому выигрывает частичный порядок.


4