Interesting variadic template trick

Hi, As some might know, I'm currently working on a reimplementation of the MPL for C++11. In doing so, I came across a technique that I did not know of and I thought I would share my discovery with the community. If this is already well known, please excuse my ignorance. The goal is to implement fast compile-time conjunction and disjunction. It goes like this: template <typename ...T> void allow_expansion(T&&...); template <typename ...T> struct or_ { static constexpr bool value = !noexcept( allow_expansion((T::value ? throw : 0)...) ); }; That's it! Note that disjunction is easily obtained in a similar way. The benefit of this technique over traditional implementations is that it's several times faster according to my benchmarks. However, you might have noticed that short-circuit evaluation is not respected so the above technique is only suitable when short-circuit evaluation is not required. If you find this interesting, see [1] for a collection of similar techniques. The one I posted above seems to be the fastest with Clang and GCC. Regards, Louis Dionne [1] https://gist.github.com/ldionne/7522393

Louis Dionne <ldionne.2 <at> gmail.com> writes:
How embarrassing; my unit test was very poor and the above trick does not seem to work. However, the following was tested more rigorously and works (with similar performance improvements): template <typename ...T> constexpr bool all_pointers(T*...) { return true; } template <typename ...T> constexpr bool all_pointers(T...) { return false; } template <typename ...T> struct or_ { static constexpr bool value = !all_pointers( ((typename std::conditional<T::value, int, void*>::type)0)... ); }; template <> struct or_<> { static constexpr bool value = false; }; Regards, Louis Dionne

On 18 November 2013 10:07, Andrey Semashev wrote:
There aren't N identical instantiations, there can only be two. Instantiating a given template specialization is only done once per translation unit. When it's already instantiated there's nothing to "optimize", the compiler just refers to the existing instantiation and uses it, similar to how it would use a non-template class. Across multiple translation units there might be duplicate instantiations that can be discarded, but that's dealt with by the linker, in the same way as duplicate copies of inline functions, vtables and RTTI info.

Andrey Semashev <andrey.semashev <at> gmail.com> writes:
Regarding the number of instantiations, others have already answered. Regarding the improvement over a naive or_, have a look at the bottom of the gist at [1]; I updated it with some benchmarks. You will see that there is indeed a noticeable improvement. Regards, Louis Dionne

On 11/18/2013 5:34 AM, Louis Dionne wrote:
Clever. Thanks for posting! -- Eric Niebler Boost.org http://www.boost.org
participants (7)
-
Andrey Semashev
-
Eric Niebler
-
Gavin Lambert
-
Jonathan Wakely
-
Louis Dionne
-
Mathias Gaunard
-
Steven Watanabe