3

So consider the following:

Used for convenience (plus C++17 "support"):

template<typename...>
using void_t = void;

template<bool B>
using bool_constant = std::integral_constant<bool, B>;

Then we have the main stuff:

//is_post_incrementable
template<typename, typename = void_t<>>
struct is_post_incrementable : std::false_type {};

template<typename T>
struct is_post_incrementable<T, void_t<decltype(std::declval<T&>()++)>> : std::true_type {};

//is_pre_incrementable
template<typename, typename = void_t<>>
struct is_pre_incrementable : std::false_type {};

template<typename T>
struct is_pre_incrementable<T, void_t<decltype(++std::declval<T&>())>> : std::true_type {};

//is_incrementable
template<typename T>
struct is_incrementable : bool_constant<is_pre_incrementable<T>::value
                                     || is_post_incrementable<T>::value> {};

We apply some tests on:

struct foo { int a = 2; };
struct foo2 { int a = 2; foo2& operator++() { ++a; return *this; } };
struct foo3 { int a = 2; foo3 operator++(int) { foo3 temp(*this); ++a; return *this; } };

int main()
{
    std::cout << is_pre_incrementable<foo>::value; //0
    std::cout << is_pre_incrementable<foo2>::value; //0 - should be 1
    std::cout << is_pre_incrementable<foo3>::value; //1 - should be 0
    std::cout << "\n";
    std::cout << is_post_incrementable<foo>::value; //0
    std::cout << is_post_incrementable<foo2>::value; //0
    std::cout << is_post_incrementable<foo3>::value; //1
    std::cout << "\n";
    std::cout << is_incrementable<foo>::value; //0
    std::cout << is_incrementable<foo2>::value; //0 - should be 1
    std::cout << is_incrementable<foo3>::value; //1
}

Those are the results I get in MVSC. The weird thing is this: If I move is_pre_increment over is_post_increment in the code, instead of 001 001 001, I get 010 010 010. It still isn't the desired 010 001 011 result.

Clang and GCC produce the expected result though.

LIVE example(Clang): http://coliru.stacked-crooked.com/a/0f9c72b2a2e851b8

LIVE example(GCC): http://coliru.stacked-crooked.com/a/beed9f24eedd4d61

Is there a logic error on my part, or is it a plain MSVC bug?

DeiDei
  • 10,205
  • 6
  • 55
  • 80
  • 3
    MSVC doesn't completely support expression SFINAE, see [this](http://blogs.msdn.com/b/vcblog/archive/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1.aspx). – Praetorian Dec 28 '15 at 17:10
  • @Praetorian Well that is just too unfortunate. Not easy writing a library in Visual Studio... – DeiDei Dec 28 '15 at 17:13
  • 3
    According to that blog post, using a dependent decltype in a partial specialization is actually supported in VS2015 update 1, but MSVC seems to have issues when you get `void_t` involved (this is possibly related to their unsupported scenario #2). If you use `decltype(void(std::declval()++))` (and likewise for pre-increment), it works correctly. – T.C. Dec 28 '15 at 17:18

0 Answers0