Variadic deduction guide not taken by g++, taken by clang++ - who is correct?

ε祈祈猫儿з 提交于 2019-11-26 07:47:54

问题


Consider the following code:

template <typename... Types>
struct list
{
    template <typename... Args>
    list(Args...) 
    {
        static_assert(sizeof...(Types) > 0);
    }
};

template <typename... Args>
list(Args...) -> list<Args...>;

int main()
{
    list l{0, 0.1, \'a\'};
}

I would expect decltype(l) to be list<int, double, char>. Unfortunately, g++ 7.2 and g++ trunk fail the static assertion. clang++ 5.0.0 and clang++ trunk compile and work as expected.

godbolt.org conformance view

Is this a g++ bug? Or Is there a reason why the deduction guide should not be followed here?


Adding a SFINAE constraint on the constructor seems to provide the desired behavior:

template <typename... Args, 
          typename = std::enable_if_t<sizeof...(Args) == sizeof...(Types)>>
list(Args...) 
{
    static_assert(sizeof...(Types) > 0);
}

godbolt.org conformance view


回答1:


This is gcc bug 80871. The issue is, we end up with this set of candidates for deduction:

template <class... Types, class... Args>
list<Types...> __f(Args... ); // constructor

template <class... Args>
list<Args...>  __f(Args... ); // deduction-guide

Both are valid (Types... can deduce as empty in the first case), but the call here should be ambiguous - neither is more specialized than the other. Types... does not participate in ordering here (similar to the example in [temp.deduct.partial]/12). So the correct behavior is to proceed to the next tiebreaker, which favors deduction-guides. Hence, this should be a list<int, double, char>.

However, gcc's behavior is to favor the constructor, hence the static_assert triggers becuase Types... would indeed be empty in that situation.



来源:https://stackoverflow.com/questions/46848129/variadic-deduction-guide-not-taken-by-g-taken-by-clang-who-is-correct

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!