Andi Wer Sonst
Andi Wer Sonst

Reputation: 1

is_enum<> in another template function does not work/compile

I have a template function that's working fine if I don't use an enum as argument type (here in condensed form; it transforms a string into anotjer type using stringstreams):

template<typename T>
void section::getVal(std::string key,T& var)
{   
    std::stringstream ss; ss.str(key);
    ss>>var;
}

Now I want that function to work with any enum, so i tried

enum slimit {lower,higher,between,nolim};

template<typename T>
void section::getVal(std::string key,T& var)
{   
    std::stringstream ss; 
    ss.str(key);
    if(!std::is_enum<T>::value)
        ss>>var;
    else
    {  
        int h;
        ss>>h;
        var=static_cast<T>(h);
    }
}

Unfortunately this doesn't compile

(error: no match for 'operator>>' (operand types are 'std::stringstream {aka std::__cxx11::basic_stringstream<char>}' and 'sensact::slimit')
                ss>>var;)

If I replace ss>>var; with something that doesn't care for the type (int n=0;) it compiles and the if-distinction/ is_enum works perfectly and the else block is executed if var is an enum type.

So how can I get it to work and why does it not compile?

Upvotes: 0

Views: 196

Answers (1)

cigien
cigien

Reputation: 60218

While an if statement only executes one branch, it still compiles all the branches. Since the code is ill-formed in one of the branches, you get an error.

If you want to conditionally compile some branches, you can use constexpr if like this:

if constexpr (!std::is_enum<T>::value)
   ss >> var;
else
{  
  int h;   // in general, std::underlying_type_t<T> instead of int,
           // to allow for other enumeration types
  ss >> h;
  var=static_cast<T>(h);
}

Thanks to @Jarod42 for the underlying_type suggestion in the comment.

Upvotes: 3

Related Questions