Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does this SFINAE pattern have a name?

Operating under the rule of "there's never anything new under the sun," I doubt that I'm the first person to come up with this trick. I figured I would stumble across something online documenting it eventually, but I haven't yet, so I figured I would ask.

Its purpose is to selectively enable certain functions provided that they're relevant, without using a derived class.

Is there a name for this pattern? And does anyone have any useful information on this pattern or a pattern that operates similarly?

template<typename T, size_t N>
class Point {
public:
  template<size_t P, typename T2=void>
  using Enable2D = typename std::enable_if<P == 2 && N == P, T2>::type;
  template<size_t P, typename T2=void>
  using Enable3D = typename std::enable_if<P == 3 && N == P, T2>::type;
  template<size_t P, typename T2=void>
  using Enable4D = typename std::enable_if<P == 4 && N == P, T2>::type;
  template<size_t P, typename T2=void>
  using Enable2DOrHigher = typename std::enable_if<P >= 2 && N == P, T2>::type;
  template<size_t P, typename T2=void>
  using Enable3DOrHigher = typename std::enable_if<P >= 3 && N == P, T2>::type;
  template<size_t P, typename T2=void>
  using Enable4DOrHigher = typename std::enable_if<P >= 4 && N == P, T2>::type;

  //Example use cases
  template<size_t P=N>
  static Enable2D<P, Point> withAngle(T angle, T magnitude = 1);
  template<size_t P=N>
  static Enable3D<P, Point> fromAngles(T psi, T theta, T magnitude = 1);

  template<size_t P=N>
  Enable2DOrHigher<P, T> const& x() const;
  template<size_t P=N>
  Enable2DOrHigher<P, T> const& y() const;
  template<size_t P=N>
  Enable2DOrHigher<P> setX(T const& t);
  template<size_t P=N>
  Enable2DOrHigher<P> setY(T const& t);

  template<size_t P=N>
  Enable3DOrHigher<P, T> const& z() const;
  template<size_t P=N>
  Enable3DOrHigher<P> setZ(T const& t);

  template<size_t P=N>
  Enable4DOrHigher<P, T> const& w() const;
  template<size_t P=N>
  Enable4DOrHigher<P> setW(T const& t);
};
like image 878
OmnipotentEntity Avatar asked Apr 15 '14 03:04

OmnipotentEntity


People also ask

What is SFINAE?

David Vandevoorde first introduced the acronym SFINAE to describe related programming techniques. We’re talking here about something related to templates, template substitution rules and metaprogramming… which make it a possibly a scary area!

How do I use SFINAE in C++?

One of the primary uses of SFINAE can be found through enable_if expressions. enable_if is a set of tools, available in the Standard Library since C++11, that internally use SFINAE. They allow to include or exclude overloads from possible function templates or class template specialization.

What is SFINAE in c++20?

We moved to an entirely new world, from some complex SFINAE code, some improvements in C++14 and C++17 to a clear syntax in C++20. In this post, we covered theory and examples of SFINAE - a template programming technique that allows you to reject code from the overload resolution sets.

What is SFINAE and tag dispatching?

SFINAE is part of the solution (along with tag dispatching ) Another example from foonathan blog - how to use SFINAE and Tag dispatching to construct a range of objects in raw memory space. Ok, but how can we write such SFINAE expressions?


1 Answers

I wouldn't call it a pattern, but it's a known technique.

Mostly reffered to as conditional interface this technique mainly addresses the problem of a compile time toggling mechanism to switch on and off interfaces of a class. The overall process provides the tools to also toggle the existence of members (so the term conditional compilation gets born).

The technique is more or less implemented the way you propose (though the lack of alias templates was not a problem prior to c++11) and the usual problem is the heavy, cluttering, confusing and "ugly" template machinery boilerplate code.

Addressing this issue, A. Alexandrescu gave a presentation about the topic. Initially there's a small mentioning of the needs for such a technique :

enter image description here

The bullet that says

  • This function works only with numbers

is reffering to your techniques and the need to have compile time conditionals to toggle the existence of functions ( conditional interface ).

The talk goes on to a proposal for a new language feature. Since we all invented the wheel a couple of times he says, why not a new language syntax, that will allow us to perform such things. His joint work with H. Sutter, produced static if a compile time toggler that would remove the needs for workarounds as the one you mention. A simple use of this would be

template<int D>
struct Vector
{
    double coordinates[D];
    static if ( D ) {
        double x() { return coordinates[0]; }
    }
    static if ( D > 1 ) {
        double y() { return coordinates[1]; }
    }
    static if ( D > 2 ) {
        double z() { return coordinates[2]; }
    }
};

OK maybe that's not the smartest use of it but I think I'm communicating the idea.

On the opposing side now, B. Stroustroup has published a paper where after aknowledging the problems static if is addressing, he explains why it's a flawed concept (pun intended :) ) and its adoption would be a disaster for the language (ouch!).

That was my two cents, judging from the level of the participants in this "conversation" I'd like to have some feedback regarding on which side they're on, or if they're part of the standardization process what will they be voting for.

like image 99
Nikos Athanasiou Avatar answered Oct 05 '22 23:10

Nikos Athanasiou