如何通过struct的成员推导出模板

时间:2017-12-14 22:09:09

标签: c++ templates

假设我有一些结构,并且每个结构都包含一个枚举作为成员。 我想调用struct的方法,但取决于struct的成员,如代码示例中所示:

#include <iostream>
#include <string>
#include <type_traits> 

enum class Type{
    lowercase = 0,
    uppercase
};

struct Low{
    static constexpr Type cp = Type::lowercase;
};

struct Up{
    static constexpr Type cp = Type::uppercase;
};


template<typename Case, typename=void>
struct Printer
{
    void print_g(const std::string& s){
        std::cout << "just s: " << s << std::endl;
    }
};

template<typename X>
struct Printer<X, std::enable_if_t<X::cp == Type::lowercase, void>>
{
    void print_g(const std::string& s){
        std::cout << "lowercase " << std::nouppercase << s << std::endl;
    }
};

template<typename X>
struct Printer <X, std::enable_if_t<X::cp == Type::uppercase, void>>
{
    void print_g(const std::string& s){
        std::cout << "uppercase " << std::uppercase << s << std::endl;
    }
};

int main()
{
    Printer<Low> pl;
    pl.print_g("hello1");
    Printer<Up> p2;
    p2.print_g("hello2");
}

但是这个解决方案看起来并不优雅。 特别是第一个模板中的 typname = void 部分。 只有代码编译。为什么会这样? 这个模板专业化还有更好(更优雅)的解决方案吗?

3 个答案:

答案 0 :(得分:1)

在C ++ 17中,您可以使用if constexpr

template <typename X>
struct Printer
{
    void print_g(const std::string& s)
    {
        if constexpr(X::cp == Type::lowercase)
        {
            std::cout << "lowercase " << std::nouppercase << s << std::endl;
        }
        else if constexpr(X::cp == Type::uppercase)
        {
            std::cout << "uppercase " << std::uppercase << s << std::endl;
        }
        else
        {
            std::cout << "just s: " << s << std::endl;
        }
    }
};

如果您无权访问C ++ 17,请考虑以下选项:

  • 使用常规if ... else语句。在您的示例中,没有需要有条件地编译的代码。

  • 在C ++ 14中实现static_if。这是我给出的一个演讲,解释了如何做到这一点:Implementing static control flow in C++14

答案 1 :(得分:1)

BufferedReader in = new BufferedReader( new InputStreamReader( new FileInputStream(fileDir), "UTF8")); Printer可以fully specialize Low

Up

请注意,枚举根本没有发挥作用。如果你需要专注于枚举,你也可以这样做。

template<class Case>
struct Printer
{
    void print_g(const std::string& s) {
        std::cout << "just s: " << s << std::endl;
    }
};

template<>
struct Printer<Low>
{
    void print_g(const std::string& s) {
        std::cout << "lowercase " << std::nouppercase << s << std::endl;
    }
};

template<>
struct Printer<Up>
{
    void print_g(const std::string& s) {
        std::cout << "uppercase " << std::uppercase << s << std::endl;
    }
};

答案 2 :(得分:1)

我可能会选择:

enum struct Casing
{
    Lower,
        Upper
};
template<Casing>
struct printer;
template<>
struct printer<Casing::Lower>
{
    ...
};
template<>
struct printer<Casing::Upper>
{
...
};