Undefined type when using std::enable_if and sizeof. (visual studio 2017)
Asked Answered
F

0

6

I get what appears to be a Visual Studio bug when I compile time test if a type with a default template parameter has some property. In the minimal example below I use std::is_integer.

When compiling the following program with Visual Studio 2017

#include <type_traits>
#include <utility>
#include <algorithm>

template<typename U,
    typename Enabled = typename std::enable_if<std::is_integral<U>::value>::type>
    struct wrapper
{
};

template<typename U, typename storage_type>
using is_small = std::is_void<typename std::enable_if <
(sizeof(wrapper<U, char>) <= sizeof(storage_type))
>::type>;

I get the following output

1>bug.cpp(13): error C2027: use of undefined type 'wrapper<U,char>'
1>bug.cpp(13): note: see declaration of 'wrapper<U,char>'

The same program does compile on g++ 6.1.

The program does compile on Visual Studio when the default parameter Enable is removed. In addition, when I perform the same sizeof(...)<=sizeof(...) test in the following template member function the program compiles fine (with is_small removed).

struct c
{
    template<typename U, typename storage_type>
    typename std::enable_if<(sizeof(wrapper<U, char>) <= sizeof(storage_type))>::value
        foo(U u, storage_type t)
    {}
};

Somehow the issue is related to the definition of is_small.

Does anyone know what the issue is? Is it a Visual Studio bug? Is there a workaround?

Edit

Reduced version:

template<class, class> struct A { };
template<int> struct B { };

template<class T> constexpr auto x = sizeof(A<T, int>); // works
template<class T> struct C : B<sizeof(A<T, int>)> { };  // works
template<class T> using D = B<sizeof(A<T, int>)>;       // doesn't work

A possible workaround could be to use x instead of is_small.

Bug report submitted: https://developercommunity.visualstudio.com/content/problem/204504/issues-with-sizeof-alias-templates-and-virtual-fun.html

Freida answered 27/2, 2018 at 7:54 Comment(5)
It is probably a MSVC bug. As a side note though, is_small doesn't make sense. That is not how you use std::enable_if.Forster
The std::enable_if for wrapper isn't that well written either. Regardless, you shouldn't ever provide a second parameter for wrapper. is_small is supposed to be either a std::true_type or std::false_type, not undefined on failureForster
I updated the example which may address these concerns.Freida
The issue seems to be related to the use of sizeof inside an alias template. Here's a reduced version that also hints at some workarounds. The problem is present in the latest released compiler version, and I haven't seen it reported on developercommunity.visualstudio.com. Do you want me to report it or do you prefer to do it yourself?Paniculate
submitted it and added some other weird behavior I saw with virtual functions and sizeof. See here developercommunity.visualstudio.com/content/problem/204504/…Freida

© 2022 - 2024 — McMap. All rights reserved.