5

Some usual template specialization like this:

template<class T>
class C
{
    void common() { ... }
    void f2 = delete;
};

template<>
class C<int>
{
    void common() { ... }
    void f1() { ... }
};

Could be represented with static_if as:

template<class T>
class C
{
    void common() { ... }

    static_if(std::is_same<T, int>::value)
    {
        void f1( ) { ... }
    }
    else
    {
        void f2( ) = delete;
    }
}

Are these directly competing features? Can template specialization do something static_if cannot? It seems like static_if can do everything template specialization can do, and much much more.

As an aside: I don't really like static_if in this context because it potentially makes what parts of an interface are available to you in any given circumstance non-obvious. Maybe template specialization still provides clearer syntax in some cases.

David
  • 27,652
  • 18
  • 89
  • 138
  • @Mechanical snail What was wrong with [C++17](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3371.html)? – David Aug 22 '12 at 20:37
  • It was redundant since you also had [tag:c++1y]. I think what happened with the C++0x/C++11 tag was that we standardized on C++0x until it was finalized, at which point it was renamed to C++11. – Mechanical snail Aug 22 '12 at 20:40
  • But just think, we could have tags for C++1y, C++17, C++2x, and maybe C++2y as well all for the same revision! – David Aug 22 '12 at 20:44
  • Methinks C++4x is most likely. – Mechanical snail Aug 22 '12 at 20:51

6 Answers6

10

One thing that static if won't do for you is the "primary" way of using template specializations -- providing generic behaviour in one place and letting the users of your code override (= specialize) it for their specific needs/data types/etc...

Grzegorz Herman
  • 1,875
  • 11
  • 22
4

No, static_if will not deprecate explicit template specialization. Explicit template specialization is a more powerful feature than static_if, providing many capabilities static_if isn't intended to. static_if is simply a more convenient and readable way to express certain things.

static_if can't do certain things explicit template specialization can, such as changing the the base classes a class inherits from.

struct S {};

template<typename T>
struct T
  static_if(is_same<T,int>::value) { : S }  // ?
{ };

template<typename T>
struct T {};

template<>
struct T<int> : S {};
bames53
  • 86,085
  • 15
  • 179
  • 244
  • You can do that with std::conditional I think - and if the only difference is changing the base class you probably would want to. – David Aug 23 '12 at 02:05
  • You could choose between inheriting from one or another class, but I don't think you could choose to inherit from a class or no class at all. – bames53 Aug 23 '12 at 05:31
  • I think you're right. +1 for a legitimate capability specialization has and `static_if` doesn't. Can you back your claim that there are _many_ though? – David Aug 23 '12 at 05:38
2

Ifs are about branching; specialization is about matching. Sometimes one is better than the other.

Here's an example straight from Alexandrescu's Modern C++ Design, Section 11.9, "Multimethods": Suppose you have a complex class hierarchy based on Shape, with virtual and non-virtual inheritance. You'd like to be able to cast among members of the hierarchy as efficiently as possible. Since virtual bases require dynamic_cast, we must allow for that, but we also want to static_cast whenever possible. Solution via cast policy:

template <typename To, typename From> struct ShapeCaster
{ 
    static To & cast(From & x) { return dynamic_cast<To&>(x); }
};

template <> struct ShapeCaster<Triangle, Shape>
{
    static Triangle & cast(Shape & x) { return static_cast<Triangle&>(x); }
};

template <typename To, typename From> To & shape_cast(From & x)
{
    return ShapeCaster<To, From>::cast(x);
}

Now wherever you're moving inside your hierarchy, you can say

To & y = shape_cast<To>::cast(x);

and you get the most efficient cast, and the policy can easily be extended.

Writing this with a series of ifs would be much harder to read.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • I had to write it out with `static_if` to compare. I put a `static_if` right into `shape_cast` to accomplish it, and it looks pretty clean. It's also about 1/4 of the code as having an external struct acting as the implementation. I'm not saying the external struct is bad, it's currently the best way to do it. But I don't think I agree with this example (post the `static_if` version yourself for comparison). – David Aug 22 '12 at 23:48
  • I'm also don't agree with your very first sentence. How many times have you written `if(x == y)` (or equivalent)? `if`s are about branching _and_ matching. – David Aug 23 '12 at 12:58
  • @Dave: This is more like `if (x == a || x == b || x = d)`, though! Templates let you specify a primary for the general case and then add exceptions unintrusively. In other words, you never have to touch the `if` statement. – Kerrek SB Aug 23 '12 at 13:16
1

The static if feature has not even made it into the standard yet. Now, assuming that the related problems are solved and it makes it into the standard, and all compilers support it, the it will be just one more tool in the toolset.

I can imagine different cases where specializations would make the code more readable/maintainable, and in all those cases, specializations would still be the way to go. Note that the greatest advantage of static if is that you can interleave code from different specializations, but that can also be a disadvantage as instead of having multiple simple specializations you might end up with a huge blob of code that gets compiled/ignored conditionally.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • If you have a case where specialization is better please post it – David Aug 22 '12 at 23:26
  • @Dave: Just pick a large class, for example `std::vector` and consider whether you'll rather have a 550 line specialization for `bool` (gcc 4.2) in it's own include file (the 550 lines is not the whole file, just the *specialization*!), or a 2000 lines `std::vector` implementation with `static if (same_type::value)` interleaved? – David Rodríguez - dribeas Aug 23 '12 at 00:20
0

I believe yes. static_if is much powerful than template specialization, especially in case when you need to specialize a small part of class, not entire definition. The only case when specialization is better - when your specialized implementation radically differs from main template/other specializations.

Rost
  • 8,779
  • 28
  • 50
0

Not taking in to account preferences, Yes only and only if it can use another template specialization!

As you all know: std::is_same<T, int>::value Is a template specialization itself!

I am not sure but I think it is implemented like:

template<typename, typename>
struct is_same{
    static constexpr bool value = false;;
};
 template<typename T>
struct is_same<T, T>{
    static constexpr bool value = true;;
};

The real question is, is there finally going to be a method for type/class comparison without template specialization? Maybe only then there will be no need for template specialization!

AKL
  • 1,367
  • 7
  • 20