[Patch] [add changelog] reduce template instantiation depth in <variant>

Barrett Adair barrettellisadair@gmail.com
Sun Nov 13 18:53:00 GMT 2016


On Sun, Nov 13, 2016 at 12:17 PM, Barrett Adair
<barrettellisadair@gmail.com> wrote:
> On Sun, Nov 13, 2016 at 3:08 AM, Tim Song <t.canens.cpp@gmail.com> wrote:
>> On Sat, Nov 12, 2016 at 3:48 PM, Barrett Adair
>> <barrettellisadair@gmail.com> wrote:
>>> On Sat, Nov 12, 2016 at 2:39 PM, Tim Shen <timshen@google.com> wrote:
>>>> On Sat, Nov 12, 2016 at 4:28 AM, Daniel Krügler
>>>> <daniel.kruegler@gmail.com> wrote:
>>>>> 2016-11-12 10:04 GMT+01:00 Barrett Adair <barrettellisadair@gmail.com>:
>>>
>>> Since there are no side-effects, and the metafunctions in play cannot
>>> SFINAE, I don't believe the semantics are actually affected by
>>> short-circuiting in this case.
>>
>> The issue is that the fold expression requires actually instantiating all the
>> is_meow_constructible &c. specializations (which in turn may trigger extra
>> instantiations) while __and_ only instantiates those needed for the result.
>> The extra instantiations can be expensive in terms of compile time but this,
>> of course, depends on the types involved. Some benchmarks would be nice.
>
> Here is a benchmark that I made with Metabench: http://jsbin.com/qalegikowi
>
> It appears that the effect on compile-time performance is negligible at worst.
> My original interest in contributing to <variant> was to reduce the compile-time
> complexity by number of types. It would be nice if to have a linear
> implementation, but I don't know yet whether that is possible.
>

My last benchmark didn't have any short-circuiting. Here's a benchmark where
the first type is not default-constructible, copy-constructible, or
move-constructible:

http://output.jsbin.com/himusodozu

Ruby template for the benchmark:

#include <variant>
#include <memory>

int main(int argc, char**) {

#if defined METABENCH

    struct T {
        int i;
        std::unique_ptr<int> x;
        T(int i) : i(i), x(nullptr) {}
    };

    <% (0..n).each do |i| %>
    struct T<%= i %> { int i; std::string x; };
    <% end %>

    using var = std::variant< T, T<%= (0..n).to_a.join(', T') %> >;

    var x(T{0});
    std::visit([](auto&& v){}, x);

#endif
}



More information about the Libstdc++ mailing list