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
is_small
doesn't make sense. That is not how you usestd::enable_if
. – Forsterstd::enable_if
forwrapper
isn't that well written either. Regardless, you shouldn't ever provide a second parameter forwrapper
.is_small
is supposed to be either astd::true_type
orstd::false_type
, not undefined on failure – Forstersizeof
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