C ++模板化类,其行为取决于类型

tag*_*cht 3 c++ templates

说你有一堂这样的课:

template <typename T>
class MyClass {
    public:
    void doSomething();
};
Run Code Online (Sandbox Code Playgroud)

在方法中,有没有办法根据这样的类型而具有不同的行为:

template <typename T> MyClass::doSomething() {
    //this is what I want:
    std::string value = "17";
    if(T == int) {
         int myInt = atoi(value.c_str());
    } else if(T == std::string) {
         std::string myString = value;
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有简单的方法可以做到这一点?
我知道我可以编写一个包装类,该包装类提供一个带有的构造函数std::string,因此我可以使用类似以下内容的东西:

T myVar(value);

但是,如果使用像这样的简单类型,那将浪费更多的资源int,我也想知道if-else-statement能够执行不同的操作。

我会很感激的答案。问候,

标记

Vit*_*meo 5

在C ++ 17中,您可以使用以下代码完全实现所需的功能if constexpr(...):

template <typename T> MyClass::doSomething() {
    //this is what I want:
    std::string value = "17";
    if constexpr(std::is_same_v<T, int>) {
         int myInt = atoi(value.c_str());
    } else constexpr(std::is_same_v<T, std::string>) {
         std::string myString = value;
    }
}
Run Code Online (Sandbox Code Playgroud)

在C ++ 14中,您可以static_if轻松实现自己的实现。我在CppCon 2016和Meeting C ++ 2016上进行了关于此的教程讨论。

template <typename T> MyClass::doSomething() {
    //this is what I want:
    std::string value = "17";
    static_if(std::is_same_v<T, int>)
        .then([&](auto) {
             int myInt = atoi(value.c_str());
        })
        .else_if(std::is_same_v<T, std::string>) 
        .then([&](auto) {
             std::string myString = value;
        })();
}
Run Code Online (Sandbox Code Playgroud)

在C ++ 11中,您可能要使用函数重载或模板专门化。前者的示例(根据注释中Jarod42的建议进行了更新):

template <typename> struct tag { };

void call_dispatch(...) { } // lowest priority

void call_dispatch(tag<std::string>) 
{ 
    std::string myString = value; 
}

void call_dispatch(tag<int>) 
{ 
    int myInt = atoi(value.c_str()); 
}
Run Code Online (Sandbox Code Playgroud)

用法:

template <typename T> MyClass::doSomething() {
    //this is what I want:
    std::string value = "17";
    call_dispatch(tag<T>{});
}
Run Code Online (Sandbox Code Playgroud)