9

__if_exists is a microsoft specific keyword for testing existence of identifiers at compile time:

msdn:__if_exists

It can come in very handy at "faked" template specialization as in some cases it provides a really much more simple, readable and better performing way than other methods like "real" specialization or overloading or whatever.

But now I have to port a big project to gnu c++ and I think I would start a little bit of crying if I would have to find other ways for the (admittedly few) occasions I used it

Ole Dittmann
  • 1,654
  • 1
  • 12
  • 20
  • Are you talking about #ifdef ? http://stackoverflow.com/questions/1802107/define-ifdef-undef-endif – karlphillip Sep 23 '10 at 14:35
  • 3
    It's a bit disconcerting to see "`__if_exists`" and "template" in the same place. In any case, if there are only a few places where it is used, you are probably far better off just reworking those few pieces of code. – James McNellis Sep 23 '10 at 14:36
  • No, its not the same as #ifdef as with #ifdef you can only test precompiler defines not e.g. class members – Ole Dittmann Sep 23 '10 at 14:44
  • 1
    found some similar questions: http://stackoverflow.com/questions/2122319/c-type-traits-to-check-if-class-has-operator-member http://stackoverflow.com/questions/257288 - also http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error – flies Sep 23 '10 at 14:48
  • 3
    @kaptnole: That's always the problem when you're relying vendor-specific goodies: when you have to use a different vendor, you have forgotten how to write code without these. I suggest you show ask here how to do without it what you needed this for. – sbi Sep 23 '10 at 14:51
  • @flies: thanks for the links. Think that would be a possible substitution for me. But like many commentators there I am also a little scared of such syntax constructs. It would render code unreadable in my opinion. – Ole Dittmann Sep 23 '10 at 15:21
  • @kaptnole you could make it readable by naming your test functions `hasMemberFoo` or something. e.g. in wiki page's top example, change the functions `void f` to `bool hasMemberType`, with the first returning true and the second returning false. you'd have to define two functions for every test -- C++ isn't really a reflective language. – flies Sep 23 '10 at 15:29
  • "C++ isn't really a reflective language" - good point. Usually there is reflection at runtime meant with that. But not even at compile time its there :-( – Ole Dittmann Sep 23 '10 at 15:49
  • To bring it up to date: Raymond Chen says not to use it. It's pre-standards, hasn't changed since 1996, was written purely for the ATL team at Microsoft, and there's better ways to do the same: "If you have code that uses __if_exists, you should consider moving to standards-compliant alternatives. For example, if you’re using __if_exists to compile a block of code only if a member function exists (which is what ATL uses it for), you can use SFINAE to do the detection and if constexpr to conditionalize the compilation." https://devblogs.microsoft.com/oldnewthing/20190828-00/?p=102812 – Chris J Aug 28 '19 at 21:44

1 Answers1

5

That's a crappy keyword in my opinion...

Unfortunately, it doesn't exist in gcc as far as I know, but then I may simply not know about it.

The proper C++ way to handle this is through the use of Concepts, ie adapt the operations carried on the type depending on some requirements.

Usually, it's carried out with traits rather than real concepts, because it's easier to put in place:

template <typename T>
struct has_dump: boost::mpl::false_ {};

And then you dump-enable your types by specializing the has_dump structure.

The simplest is to define 3 methods, one to route, the two others to execute the different branches:

template <typename T>
void dump(T& t, boost::mpl::true_ const& dummy)
{
  t.Dump();
}

template <typename T>
void dump(T& t, boost::mpl::false_ const& dummy)
{
  std::cout << typeid(T).name() << " does not have Dump\n";
}

template <typename T>
void dump(T& t) { dump(t, has_dump<T>()); }

Another use of the type traits would be in conjunction with the enable_if facilities:

template <typename T>
typename boost::enable_if< has_dump<T> >::type dump(T& t)
{
  t.Dump();
}

// disable_if exists too...

Here, instead of a runtime error message, you can get a compile-time error if the type does not have has_dump enabled, not sure if that's you want.

However both those methods are quite cumbersome, since the detection isn't automated. That is why there is the Boost.Concept library.

The idea is that the check will be performed by a Concept object, created to test the requirements, and thus you don't have to specialize traits any longer, which make easier on the development. However I have always found the documentation of Boost.Concept to be somewhat lacking.

Matthieu M.
  • 251,718
  • 39
  • 369
  • 642
  • 2
    Well your alternative is also way too complicated for my purpose but I will accept your answer as a "no" if nobody comes up with a real simple "yes" in a few days. – Ole Dittmann Sep 23 '10 at 15:55
  • @kaptnole: I agree it's verbose, the whole of concepts was to simply this... let's hope they'll make it in C++1x – Matthieu M. Sep 23 '10 at 16:57
  • Could you give more information on the following statement: "And then you dump-enable your types by specializing the has_dump structure?" I think you are referring to something like "template<> struct has_dump:boost::mpl::true_ {};" as discussed in the article found at http://en.cppreference.com/w/cpp/language/template_specialization but I am not certain. – Ben Key Jul 09 '15 at 16:44
  • @BenKey: Yes, that's exactly what I was referring to. – Matthieu M. Jul 09 '15 at 17:49
  • 1
    @MatthieuM. Ummm, as the person who came up with __if_exists, well I did introduce it 20 years ago. It was a primitive form of meta-programming SFINAE that I needed at the time in order to implement AOP in the VC 6.0 compiler. I admit it's completely lame compared to "the future" :) – user3291110 May 01 '17 at 09:12
  • The funny thing is I actually came here looking how to do it portably with current compilers :-) :+1: – user3291110 May 01 '17 at 09:18
  • 1
    @user3291110: Wow! 20 years ago I knew only BASIC (well two versions of it). Takes me back... – Matthieu M. May 01 '17 at 09:26
  • well it looks like you know more about current C++ than I do now, I can tell you that. but hey, I'm back at it... crazy huh. nice answer btw. – user3291110 May 01 '17 at 09:29
  • 1
    @user3291110: It's for this kind of random encounters that I find Internet an extraordinary place :) – Matthieu M. May 01 '17 at 10:45
  • 2
    [The sad history of Visual Studio’s custom `__if_exists` keyword](https://devblogs.microsoft.com/oldnewthing/20190828-00/?p=102812) – phuclv Sep 01 '19 at 13:44