2

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.

Community
  • 1
  • 1
  • What about [specialization](http://coliru.stacked-crooked.com/a/3f860354bf54a365)? –  Dec 12 '14 at 03:13
  • @remyabel That does work for that specific case, but if that specific case were what I was looking for I could just go with WillCast and say "int". I'm looking for something that does pattern matching and produces a lot of cast operators... but only under the right cases. – HostileFork says dont trust SE Dec 12 '14 at 03:16
  • How about [this](http://coliru.stacked-crooked.com/a/104248a4014efff6)? It uses the same trick as the link you have in your question. –  Dec 12 '14 at 03:28
  • @HostileFork Cool question - I didn't even realize this was possible until I started trying things. – Barry Dec 12 '14 at 03:35

1 Answers1

4

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
Barry
  • 286,269
  • 29
  • 621
  • 977