не может скомпилировать экземпляр шаблона функции, содержащий "if constexpr" - PullRequest
0 голосов
/ 07 мая 2018

Извините за смутное название, но я не смог придумать лучшего.

Я написал функцию для выравнивания контейнеров:

template <typename Container, typename OutIt>
void flatten(const Container& container, OutIt res)
{
    if constexpr (std::is_convertible_v<typename Container::value_type, typename std::iterator_traits<OutIt>::value_type>)
    {
        for (const auto& value : container)
        {
            *res = value;
            ++res;
        }
    }
    else
    {
        for (const auto& subContainer : container)
            flatten(subContainer, res);
    }
}

И я хотел, чтобы оно использовалось как:

vector<vector<int>> test = {{1}, {2, 3, 4}, {5, 6}, {7}};
vector<int> res;
flatten(test, std::back_inserter(res));

Это должно в основном копировать все вложенные значения из test в res, так что res == { 1, 2, 3, 4, 5, 6, 7 }.

Однако, если я хочу скомпилировать код, компилятор выдает некоторые ошибки, которые в основном говорят о том, что код в ветви else компилируется вместо блока if constexpr.

т.е. Первый экземпляр - void flatten<vector<vector<int>>, OutIt>(), который является правильным. Второй экземпляр (который запускается блоком else) - это void flatten<vector<int>, OutIt>(), что также правильно. Но для 2-го экземпляра выражение if constexpr должно иметь значение true, так как vector<int>::value_type равно int и std::iterator_traits<OutIt>::value_type> также равно int. Но каким-то образом компилятор пытается создать третий шаблон void flatten<int, OutIt>(), который вызывает ошибки компилятора (потому что я пытаюсь перебрать целое число).

Почему компилятор создает экземпляр 3-го шаблона?

1 Ответ

0 голосов
/ 07 мая 2018

Вы передаете std::back_insert_iterator, для которого value_type равно void. Так что ваша истинная ветвь оператора if никогда не создается.

Возможное решение - попытаться проверить, что делает ветка. Это может быть сделано с std::is_assignable и некоторыми шаблонами, включающими decltype(*declval<OutIt>()).

...