Search code examples
c++c++11templatesvisual-c++decltype

Decltype cast operator in Visual Studio


Consider following code example:

#include <algorithm>

template<class T, class U>
struct lazy_caller{
    lazy_caller(T &&one, U &&two) : m_one(one), m_two(two){} 

    operator decltype(std::max(T(), U()))() const {
        return std::max(m_one, m_two);
    }

    T m_one;
    U m_two;
};

int main()
{
    lazy_caller<int, int> caller(1, 2);
    int i = caller;
    return 0;
}

As you may imagine, in real code I wanted to do more sophisticated type deduction to create appropriate conversion operator. Anyway - this code does not compile in VS2017 (and I guess the same is with earlier ones) - and so I would like to ask if there is any workaround for this issue? I have already tried:

operator auto () const

It also generates compiler errors like:

source_file.cpp(8): error C2833: 'operator function-style cast' is not a recognized operator or type

Is there any solution for this problem with msvc? Because gcc has not problem with neither operator auto nor operator decltype(..).


Solution

  • Is there any solution for this problem with msvc?

    What about passing through an using alias?

    using maxType = decltype(std::max(T(), U()));
    
    operator maxType () const {
        return std::max(m_one, m_two);
    }
    

    or, maybe better, using std::declval(),

    using maxType = decltype(std::max(std::declval<T>(), std::declval<U>()));
    

    If this doesn't work, you can try with a third defaulted template type for the lazy_caller class; something like

    template <typename T, typename U,
       typename R = decltype(std::max(std::declval<T>(), std::declval<U>()))>
    struct lazy_caller
     {
       lazy_caller(T && one, U && two) : m_one(one), m_two(two)
        { } 
    
       operator R () const
        { return std::max(m_one, m_two); }
    
       T m_one;
       U m_two;
     };