Проблема Clang: неявное преобразование типов во время строительства

Синопсис

Я изо всех сил пытаюсь сделать код C++11 совместимым с Clang и столкнулся со случаем, когда GCC >= 4.6 принимает код, а Clang >= 3.1 — нет. Кланг считает конструктор-кандидат нежизнеспособным.

Details

Вот урезанный пример, чтобы проиллюстрировать проблему:

#include <utility>

template <typename...>
struct T;

template<>
struct T<>
{
    typedef T super;

    constexpr T() { }

    template <typename... Args>
    T(Args&&...) { }

};

template <typename Head, typename... Tail>
struct T<Head, Tail...> : T<Tail...>
{
    typedef T<Tail...> super;

    Head head;

    T(Head arg) : super(), head(std::move(arg)) { }
};


struct void_type
{
    constexpr void_type() { }
    constexpr void_type(const void_type&) { }
    void_type& operator=(const void_type&) = default;

    template <typename Arg0, typename... Args>
    void_type(Arg0&&, Args&&...) { }
};

struct atom { };

int main()
{
    atom a;
    T<void_type> t(a);

    return 0;
}

Ошибка, которую я получаю:

ctor-init.cpp:44:18: error: no matching constructor for initialization of 'T<void_type>'
    T<void_type> t(a);
                 ^ ~
ctor-init.cpp:19:8: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'atom' to 'const T<void_type>' for 1st argument;
struct T<Head, Tail...> : T<Tail...>
       ^
ctor-init.cpp:25:5: note: candidate constructor not viable: no known conversion from 'atom' to 'void_type' for 1st argument;
    T(Head arg) : super(), head(std::move(arg)) { }
    ^
1 error generated.

Я не понимаю, почему clang жалуется на отсутствие возможности преобразования, потому что я думаю, что этот «универсальный» конструктор должен работать:

template <typename Arg0, typename... Args>
void_type(Arg0&&, Args&&...) { }

Так что ошибка, которая меня смущает:

ctor-init.cpp:25:5: note: candidate constructor not viable: no known conversion from 'atom' to 'void_type' for 1st argument;
    T(Head arg) : super(), head(std::move(arg)) { }
    ^

В конце концов, GCC принимает код. Возможно, это ошибка Clang? (Я использую последнюю версию Clang из репозитория LLVM git.)

10
задан mavam 31 May 2012 в 21:39
поделиться