enable_if on explicit templated cast operator gives "invalid static_cast"

I'm attempting to do a templated explicit cast operator. I found that notationally, you actually can put an expression with type traits and std::enable_if in the operator's "name" slot. But the following test doesn't give the desired behavior:

#include <iostream>
#include <type_traits>

class WillCast {
public:
    explicit operator int () {
       return 1020;
    }
};

class WontCast {
public:
    template <typename T>
    typename std::enable_if<
        std::is_same<T, int>::value, int
    >::type toInteger()
    {
       return 1324;
    }

    template <typename T>
    explicit operator typename std::enable_if<
        std::is_same<T, int>::value, int
    >::type ()
    {
       return 304;
    }
};

int main() {
    std::cout << static_cast<int>(WillCast{}) << "\n";   // ok
    std::cout << WontCast{}.toInteger<int>() << "\n";    // ok
    /* std::cout << static_cast<int>(WontCast{}); */     // error 
};

The error coming back from gcc 4.8.2 is:

test.cpp: In function ‘int main()’:
test.cpp:27:45: error: invalid static_cast from type ‘WontCast’ to type ‘int’
    std::cout << static_cast<int>(WontCast{});

If what I'm trying to do were not possible, I wouldn't be surprised. But it seems to think the syntax is all right, it's just not seeming to behave consistently between the "nearby" behaviors seen by WontCast::toInteger() and WillCast::operator int().

(This is a reduced example, of course my desired enable_if is trickier.)


UPDATE - "Sidebar intelligence(tm)" has thrown up How can I use std::enable_if in a conversion operator? which I didn't find through "BeforeYouAsked intelligence(tm)". I will look and see if it helps. Well, the solution used there doesn't seem to apply, because WontCast isn't a templated class. So not helping here.

Upvotes: 2

Views: 700

Answers (1)

Barry
Barry

Reputation: 303156

If you move the enable_if part into the template, this works:

template <typename T,
          typename = typename std::enable_if<std::is_same<T, int>::value>::type
          >
explicit operator T()
{
    return 304;
}

Given that:

int i = static_cast<int>(WontCast{}); // ok
double d = static_cast<double>(WontCast{}); // invalid static_cast

Upvotes: 4

Related Questions