Ответ 1
Действительно, это была ошибка Клана. Оказалось, что вариативные конструкторы ошибочно отмечены как явные. Исправлено в Clang r158040.
Я борюсь с тем, чтобы сделать код С++ 11 Clang совместимым и столкнулся с ситуацией, когда GCC >= 4.6 принимает код, а Clang >= 3.1 - нет. Кланг считает candidate constructor not viable
.
Ниже приведен пример сокращения, чтобы проиллюстрировать проблему:
#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 жалуется на отсутствие возможности конвертации, потому что я думаю, что этот конструктор "catch-all" должен работать:
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 из репозитория LLVM git.)
Действительно, это была ошибка Клана. Оказалось, что вариативные конструкторы ошибочно отмечены как явные. Исправлено в Clang r158040.