expl0it3r
expl0it3r

Reputation: 335

Multiple Return Types with templates and switch case in C++

I am trying to get a multiple return type function working in C++, by providing an enum value as a template argument.

Here is my code:

static enum class TEXTAttribute {
    ORIGIN_PROPORTION, FONT_NAME
};

struct MyStruct {
    std::string font_name;
    sf::Vector2f origin_proportion;
};
template<TEXTAttribute ATTRIBUTE>
auto GetTextAttribute(const MyStruct& style){
    switch (ATTRIBUTE) {
    case TEXTAttribute::FONT_NAME: {return style.font_name; break; }
    case TEXTAttribute::ORIGIN_PROPORTION: {return style.origin_proportion; break; }
    }
}
int main() {
    GetTextAttribute<TEXTAttribute::FONT_NAME>(MyStruct{});
}

I thought I would be able to do this since I am using auto? I just seem to get an error saying that the return type was unable to be deduced. Is this even possible?

Upvotes: 0

Views: 595

Answers (3)

Nicol Bolas
Nicol Bolas

Reputation: 473457

What you want is semi-possible, but not with switch. You have to use C++17's if constexpr:

template<TEXTAttribute ATTRIBUTE>
auto GetTextAttribute(const std::array<MyStruct,3> statestyles)
{
    auto& style = statestyles.at(0);
    if constexpr(ATTRIBUTE == TEXTAttribute::FONT_NAME)
        return style.font_name;
    if constexpr(ATTRIBUTE == TEXTAttribute::ORIGIN_PROPORTION)
        return style.origin_proportion;
}

The untaken return branches are discarded, since ATTRIBUTE is a template parameter.

Upvotes: 1

bipll
bipll

Reputation: 11940

switch is a runtime construct. Use if constexpr:

    if constexpr (ATTRIBUTE == TEXTAttribute::FONT_NAME) return style.font_name;
    else if constexpr(ATTRIBUTE == TEXTAttribute::ORIGIN_PROPORTION) {
        return style.origin_proportion;
    }

Just remember to put all the parameter value-dependent code in appropirate if constexpr/else branches.

Upvotes: 0

cigien
cigien

Reputation: 60228

There's no problem deducing the auto, but the issue is that auto deduces to different return types. If you want to have different return types, you need a compile construct such as if constexpr:

template<TEXTAttribute ATTRIBUTE>
auto GetTextAttribute(const std::array<MyStruct,3> statestyles) {
    auto& style = statestyles.at(0);
    if constexpr(ATTRIBUTE == TEXTAttribute::FONT_NAME)  
        return style.font_name;
    else if constexpr(ATTRIBUTE == TEXTAttribute::ORIGIN_PROPORTION)  
       return style.origin_proportion;
}

Upvotes: 1

Related Questions