从函数返回带有值模板参数的类模板

Return a class template with value template arguments from function

本文关键字:参数 函数 返回      更新时间:2023-10-16

假设我有一个简单的模板类:

template <typename ElementType, ElementType Element>
class ConsecutiveMatcher
{
public:
    bool operator () (ElementType lhs, ElementType rhs)
    {
        return lhs == Element && rhs == Element;
    }
};

我通常会通过提供一个函数来使实例化比ConsecutiveMatcher<wchar_t, L''>()更简单,该函数可以根据参数类型推断模板参数类型:

template <typename ElementType>
ConsecutiveMatcher<ElementType, Element /* ?? */> 
    MakeConsMatcher(ElementType Element)
{
    return ConsecutiveMatcher<ElementType, Element>();
}

但是,在这种情况下,MakeConsMatcher(L'')将不起作用,因为函数需要返回一个类,该类的模板不仅包含类型,还包含值。

如何从既有类型模板参数又有值模板参数的函数返回类模板?

您想将运行时计算的值转换为模板参数吗?这是不可能的。

我只是在寻找一种方法来省略wchar_t,并在实例化过程中使用自动类型推导。

我可以想象这样的情况:

  1. 只有在运行时才知道的参数类型(您对此一无所知):您无法使用模板处理它:您将希望重新设计代码并使用继承和虚拟函数(或者,可能将模板和继承混合使用)

  2. 编译时已知参数类型,运行时已知参数值:在模板参数列表中留下参数的类型,并将参数传递给构造函数,然后为了用户方便,使工厂函数推断类型

    template<typename T>
    struct MyType
    {
        template <class T>
        MyType(const T& defaultValue) :
             value(defaultValue)
        {}
        T value;
    };
    template<typename T>
    MyType<T> MyFactory(const T& defaultValue)
    {
        return MyType<T>(defaultValue);
    }
    int main()
    {
        char c = 'a';
        wchar_t w = L'a';
        int i = 42;
        float f = 3.14f;
        auto mt_char = MyFactory(c);
        auto mt_wchar = MyFactory(w);
        auto mt_int = MyFactory(i);
        auto mt_float = MyFactory(f);
    }
    
  3. 在编译时,您知道一个类型列表,并希望它们的行为不同(例如,具有不同的默认值):为列表中的每个类型进行模板专门化,然后,为了用户方便,创建typedefs

      template<typename T> struct MyType
      {
            MyType(const T& defaultValue) :
        value(defaultValue)
              {}
         T value;
     };
     template<>
     struct MyType <char>
     {
        MyType() :
         value('c')
        {}
        char value;
     };
    
     template<>
     struct MyType <wchar_t>
     {
        MyType() :
         value(L'w')
        {}
        wchar_t value;
     };
     typedef MyType<char> MyTypeChar;
     typedef MyType<wchar_t> MyTypeWchar;
     int main()
     {
       MyTypeChar mt_char_default;
       MyTypeWchar mt_wchar_default;
     }
    

在这种情况下,用户仍然可以实例化自己的专业化。这种方法的例子是std::basic_string类。此外,如果使类成员staticstatic const,并且对于积分类型,只需在成员列表中定义即可,则可以简化您的专业化:

template<>
struct MyType <char>
{
    static const char value = 'c';
};