Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to detect portably that a standard header is included using macros?

Tags:

c++

utility

I want to make an equivalent to boost::swap and in my environment, standard headers can, or cannot be included. Depending on project licencing and other stuff.
I'd like to make portions of the code protected by guard detectors:

Let's consider one compilation unit.
project specific, afore-written potential includes:

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

later in project code included from my swap utility header:

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
  }
}

I simplified because we are not talking about details of the ADL trick here, but it will get included.
here for the reference of what I am talking about, but this is irrelevant to this question:
http://www.boost.org/doc/libs/1_57_0/boost/core/swap.hpp

So this question is about, how can I detect standard header inclusion ? the _ALGORITHM_ guard is present in visual studio provided header, but I read nowhere on http://www.cplusplus.com/reference/algorithm/ that it should have any macro that I can check.

(final note: this question is a little bit XY biased. What I really want is to detect the presence of the std::swap function, not the header.)

like image 210
v.oddou Avatar asked Mar 04 '15 02:03

v.oddou


People also ask

When to use header files in C?

Your own header files contain declarations for interfaces between the source files of your program. Each time you have a group of related declarations and macro definitions all or most of which are needed in several different source files, it is a good idea to create a header file for them.

What should header file contains?

A header file is a file with extension . h which contains C function declarations and macro definitions to be shared between several source files. There are two types of header files: the files that the programmer writes and the files that comes with your compiler.

What is the primary purpose of header files?

The primary purpose of a header file is to propagate declarations to code files. Header files allow us to put declarations in one location and then import them wherever we need them. This can save a lot of typing in multi-file programs. This program prints “Hello, world!” to the console using std::cout.


1 Answers

One option you have it to make your overload a "worse match" than the alternatives. Then, only if they don't already exist will your version be selected:

#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);
}  

What's happening:

When there are two candidate function template specializations, the compiler performs "Partial ordering of function templates"('03 14.5.5.2). This checks if the function template parameters of the one template can be used to specialize the other.

For each template we'll use dummy parameters T1 and T2 and we create dummy argument lists using these types:

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

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

Specializing our swap using the dummy arguments from std::swap gives:

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

The deduced T is T1 and deduction has succeeded.

Specializing std::swap using the dummy arguments for our swap gives:

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

The deduced types for T are not the same, and so this is considered a deduction failure.

Therefore, the synthesized arguments of std::swap can be used to specialize our template, but the synthesized arguments of our template cannot be used to specialize std::swap. std::swap is seen as being more specialized and so wins the partial ordernig.

like image 82
Richard Corden Avatar answered Nov 10 '22 07:11

Richard Corden