Функция Variadic не компилируется с Clang - PullRequest
0 голосов
/ 03 октября 2018

Прежде всего, я прошу прощения, если это дубликат, я буду рад его устранить, но я даже не уверен, что проблема / диагностика здесь.

В любом случае, мой код здесь работает с gccа не лязг - почему это так?Я явно не могу понять, почему Clang не может скомпилировать это.

#include <iostream>
#include <type_traits>

using std::cout;
using std::endl;


template <typename T, typename... Args, typename std::enable_if<!sizeof...(Args)>::type* = nullptr>
void func(int start_size, int idx)
{
    cout << start_size << " " << idx << endl;
    return;
}

template <typename T, typename... Args, typename std::enable_if<sizeof...(Args)>::type* = nullptr>
void func(int start_size, int idx)
{

    if((idx + 1) == int(start_size - int(sizeof...(Args))))
       {
           cout << start_size << " " << idx << endl;
           return;
       }
       func<Args...>(start_size, idx);
}

template <typename... Args>
void func_wrapper(int idx)
{
    func<Args...>(sizeof...(Args),idx);
}


int main()
{
    func_wrapper<int,double,char>(1);

}

Ошибка:

prog.cc:37:5: error: no matching function for call to 'func'
    func<Args...>(sizeof...(Args),idx);
    ^~~~~~~~~~~~~
prog.cc:44:5: note: in instantiation of function template specialization 'func_wrapper<int, double, char>' requested here
    func_wrapper<int,double,char>(1);
    ^
prog.cc:16:6: note: candidate template ignored: requirement '!sizeof...(Args)' was not satisfied [with T = int, Args = <double, char>]
void func(int start_size, int idx)
     ^
prog.cc:23:6: note: candidate template ignored: substitution failure [with T = int, Args = <double, char>]: non-type template argument evaluates to 2, which cannot be narrowed to type 'bool'
void func(int start_size, int idx)
     ^
1 error generated.

Wandbox: https://wandbox.org/permlink/yqki47uYcwUlE013

Ответы [ 2 ]

0 голосов
/ 03 октября 2018

В дополнение к отсутствующему явному преобразованию из std::size_t в bool, для которого потребуется код как

std::enable_if<sizeof...(Args) != 0>

Есть и другая ошибка:

temp # res-8.3

Программа некорректна, диагностика не требуется, если:

[..]

каждая действительная специализация вариационного шаблонатребуется пустой пакет параметров шаблона,

Так что

template <typename T,
          typename... Args,
          typename std::enable_if<sizeof...(Args) == 0>::type* = nullptr>

недопустимо.
(Существует также void* = nullptr, что может быть проблематично).

Вместо этого вы можете написать это с двумя перегрузками:

template <typename T>
void func(int start_size, int idx)
{
    cout << start_size << " " << idx << endl;
}

template <typename T, typename T2, typename... Args> // Addition of T2, and change sizeof...
void func(int start_size, int idx)
{
    if ((idx + 1) == int(start_size - int(1 + sizeof...(Args)))) {
        cout << start_size << " " << idx << endl;
        return;
    }
    func<T2, Args...>(start_size, idx);
}
0 голосов
/ 03 октября 2018

Clang правильно при отклонении этого кода.Чтобы устранить ошибку, вы должны явно применить преобразование:

std::enable_if<bool(sizeof...(Args))>

. Объяснение:

[temp.arg.nontype] / 5

Следующие преобразования выполняются для каждого выражения, используемого в качестве нетипового аргумента шаблона.Если нетипизированный шаблонный аргумент не может быть преобразован в тип соответствующего шаблонного параметра, то программа некорректна.

(5.1) Для нетипового шаблонного параметра целочисленного или перечислимого типа, преобразования, разрешенные в преобразованном константном выражении ([expr.const]), применяются .

Тогда [expr.const] / 3 говорит, чтосужающее преобразование не рассматривается автоматически:

Преобразованное константное выражение типа T является литеральным константным выражением, неявно преобразованным в тип T, где неявное преобразование (если оно есть) разрешено в литеральном константном выражениии последовательность неявного преобразования содержит только пользовательские преобразования, преобразования lvalue-в-значение ([conv.lval]), интегральные преобразования ([conv.prom]) и интегральные преобразования ([conv.integral]), другиечем сужающиеся преобразования ([dcl.init.list])

Таким образом, для этого случая сужающее преобразование с std::size_t до bool, это шоне должно быть явным: bool(sizeof...(Args))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...