1

Here's an extremely simple code:

#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);
}

Don't ask what the hell this code is for. It doesn't matter. It's just refined and simplified example of what I found. The important thing is it seems to be valid C++ 17 code anyway.

test() is enabled (in further SFINAE situation) only when V is std::array. Yeah, I know that I can just do template<class T, int N> void test(array<T, N>& v) but this more dirty template parameters help me in some cases for not having int N. (Trust me!)

Anyway this C++ 17 code fails to compile in Visual Studio 2019 with C++ 17 setup. However it works well in GCC and Clang.

Hours ago, I posted related question here. The only thing I could found in common is that they're about some complicated templates and that they result in same error codes :

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

Questions are....

  1. Is that a valid C++ 17 code?
  2. Then why does MSVC fail to compile?
  3. What is the relation with my previous question?
  4. How should I deal with this if I decided to just use MSVC?
i.stav
  • 444
  • 3
  • 9
  • 2
    By the way, is there a special reason that you are still using `::value` and `::type` instead of the `_t`s and `_v`s? – L. F. Jul 04 '19 at 12:03
  • @L.F. I know what you're saying about. **But** I can overload ``array_size()`` and always choose ``V`` that has ``value``. After I add some other ``test()``s then it becomes completely typical SFINAE overloading resolution. (not a hard error) – i.stav Jul 04 '19 at 12:15
  • Sorry, I was wrong. Deleted my previous comment. – L. F. Jul 04 '19 at 12:17
  • @L.F. That's ok. (I appreciate your interest on this question) BTW what are ``_t`` and ``_v``? – i.stav Jul 04 '19 at 12:21
  • For example, you can write `enable_if_t` in place of `typename enable_if::type`, and `is_same_v` in place of `is_same::value`. – L. F. Jul 04 '19 at 12:22
  • Interestingly enough, rewriting the function in a different way allows compilation: https://godbolt.org/z/mDPPq7 – CuriouslyRecurringThoughts Jul 04 '19 at 12:27
  • Looks like a regression, since the code works in VS 2017 15.9. – bogdan Jul 04 '19 at 14:16

1 Answers1

0

I do not know what exactly is tripping MSCV's compiler but the replacing default pointer with a default type parameter seems to work:

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)

Both should be valid C++17 as the second argument can be deduced from the V. Perhaps the constexpr functions are not as per the standard in MSCV yet.

Quimby
  • 17,735
  • 4
  • 35
  • 55
  • Thanks. I think there's something for MSVC in situation of ``constexpr function call as non-type argument`` + ``enable_if_t<>*`` – i.stav Jul 04 '19 at 12:35