Функция enable_if + is_same + constexpr приводит к сбою MSVC (но хорошо работает в Clang, GCC) - PullRequest
1 голос
/ 04 июля 2019

Вот чрезвычайно простой код:

#include <tuple>
#include <type_traits>
#include <array>

template <class T> struct TypeHolder {};

template<class T, size_t N>
constexpr size_t array_size(TypeHolder<std::array<T,N>>)
{
    return N;
};

using AnyType = int;
template <class V, typename std::enable_if<std::is_same<V,
 std::array<typename V::value_type, array_size(TypeHolder<V>())>>::value, AnyType>::type* = nullptr>
    void test(V & v)
{

}

int main()
{
    std::array<int, 5> x;
    test(x);
}

Не спрашивайте, для чего этот код. Это не важно Это просто уточненный и упрощенный пример того, что я нашел. Важно то, что в любом случае это правильный код C ++ 17.

test() разрешено (в дальнейшей ситуации с SFINAE), только если V равно std::array Да, я знаю, что могу просто сделать template<class T, int N> void test(array<T, N>& v), но более грязные параметры шаблона в некоторых случаях помогают мне не иметь int N. (Поверь мне!)

В любом случае этот код C ++ 17 не компилируется в Visual Studio 2019 с настройкой C ++ 17. Однако хорошо работает в GCC и Clang.

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

error C2672:  no matching overloaded function found
error C2783:  could not deduce template argument for '__formal'

Вопросы есть ....

  1. Это действительный код C ++ 17?
  2. Тогда почему MSVC не компилируется?
  3. Какое отношение имеет мой предыдущий вопрос?
  4. Как мне справиться с этим, если я решил просто использовать MSVC?

1 Ответ

0 голосов
/ 04 июля 2019

Я не знаю, что именно отключает компилятор MSCV, но замена указателя по умолчанию на параметр типа по умолчанию, похоже, работает:

template <typename V, typename = std::enable_if_t<std::is_same_v<V,
 std::array<typename V::value_type, array_size(TypeHolder<V>())>>, AnyType>>
    void test(V & v)

Оба должны быть действительными C ++ 17, поскольку второй аргумент может быть выведен из V. Возможно, функции constexpr пока не соответствуют стандарту MSCV.

...