【问题标题】:Specializing a template class member function for only one type只为一种类型专门化模板类成员函数
【发布时间】:2010-11-11 21:24:01
【问题描述】:

我有一个模板类,它有很多功能,但本质上是一个向量类。我想为 bool 类型添加一个函数。

#include <vector>
template <typename T>
class reflected{
    private:
        T*dev_;
        T*host_;
        ar_size size;
        reflected<T>& operator=(reflected<T>& rhs);//do not impliment.  assign not allowed.
        reflected( reflected<T>& old);  //do not impliment. Copy not allowed.
    public:
        reflected():size(0L),dev_(NULL),host_(NULL){}
        reflected(ar_size n):size(n),dev_(NULL),host_(NULL){init();}
        reflected(const T*x,ar_size n):size(n),dev_(NULL),host_(NULL){init();set(x);}
        ~reflected();
        void init();
        void init(ar_size n);
        void init(const T*x,ar_size n);
        void set(const T * x);
        void setat(ar_index i, T x);
        const T getat(ar_size i);
        const T * devPtr();
        const T operator [](const ar_index i);
        ar_size length(){return size;}
};

我想在反射类的特殊情况下添加一个函数vector&lt;ar_index&gt; reflected&lt;bool&gt;::which(),这是唯一有意义的情况。做这个的最好方式是什么。编译器似乎不喜欢将 which() 添加到反射中,并且只为 bool 定义它。

【问题讨论】:

    标签: c++ templates template-specialization


    【解决方案1】:

    你可以像这样在类模板中定义它

    template <typename T> struct id { typedef T type; };
    
    template <typename T>
    class reflected{
        private:
            /* ... */
            vector<ar_index> which(id<bool>) { 
              /* ... */
            }
        public:
            /* ... */
            vector<ar_index> which() { return which(id<T>()); }
    };
    

    如果您在没有给出正确定义的reflected&lt;T&gt; 上调用which,这会导致编译时错误。

    【讨论】:

    • 我不确定他/她是否希望该方法失败,或者只是因为它没有被定义而是为 bool。无论如何,您的解决方案非常好:)
    • 这与 John Dibling 的回答相比如何?额外的“间接”有什么好处吗?谢谢
    • @icecrime 你不需要复制构造函数并且它可以扩展。如果某些函数只对int 有意义而对其他人无效,则不需要另一个派生类。我喜欢为此使用重载。
    • @Johannes 抱歉,我指的是 John Dibling 的答案,它不依赖于继承,而是依赖于仅为 reflected&lt;bool&gt; 专业化定义的 which() 方法
    • @icecrime 哦,对不起,我看错了 :) John's 没有给出编译时错误。稍后它将无法链接(对于大型程序来说可能会更晚)。
    【解决方案2】:

    如果只想添加一个问题,可以将继承与特化结合起来:

    template <typename T>
    class reflected_base { 
        // your current 'reflected' contents go here
    }; 
    
    template <typename T>
    class reflected : public reflected_base { };
    
    template <>
    class reflected<bool> : public reflected_base {
        vector<ar_index> which();
    };
    

    这种方法的缺点是您必须为每个特化重新实现某些操作(析构函数、复制构造函数等)。另一种选择是:

    template <typename T>
    class specialized_reflected { };
    
    template <>
    class specialized_reflected<bool> {
    public:
        vector<ar_index> which();
    };
    
    template <typename T>
    class reflected : public specialized_reflected<T> {
        // your current 'reflected' contents go here
    };
    

    但是,依赖名称查找存在潜在问题。第三种选择(可能也是我会选择的)是使用非成员函数:

    vector<ar_index> which(reflected<bool>&);
    

    【讨论】:

    • +1 击败我 90 秒!
    • 您需要 &lt;T&gt; 用于 reflect_base 也在反射的声明中。但是,为什么您需要reflected_base?
    • @Diego:这样主要的reflected 模板和reflected 的每个特化都可以使用相同的成员。
    • 也就是说,约翰内斯的回答要好得多(像往常一样......)
    • @James:但这可以通过将所需的功能添加到专业化reflected&lt;bool&gt;...
    【解决方案3】:

    无法按照您想要的方式直接完成。但是您可以通过不为除专用类之外的任何类定义reflected() 来获得类似的结果。然后,如果您尝试在不受支持的类上使用它,则会出现线性错误。

    #include <string>
    #include <sstream>
    using namespace std;
    
    template<typename A>
    class Gizmo
    {
    public:
        Gizmo(){};
        int which();    
    };
    
    template<> int Gizmo<bool>::which()
    {
        return 42;
    }
    
    int main()
    {
    
        Gizmo<bool> gb;
        gb.which();
    
        Gizmo<int> gi;
        gi.which(); // LINKER ERROR for Gizmo<int>which()
    
        return 0;
    }
    

    【讨论】:

    • 快!但我会将其描述为“将 which() 添加到反射并仅将其定义为 bool。”这就是 OP 所说的他正在做的事情。
    • 我将 OP 的描述解读为她试图为 bool 专业化重新定义该类。
    • 重读后你可能是对的。如果 OP 回应这是他正在做的事情,我会删除它。
    • 这是我正在尝试的,它不起作用编译器不喜欢它。
    【解决方案4】:

    您可以将vector&lt;ar_index&gt; reflected&lt;bool&gt;::which() 添加到reflected&lt;bool&gt;(并且只能添加到它,而不是一般模板)。如果出现错误,可能是您没有正确地进行模板特化...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-20
      • 1970-01-01
      • 1970-01-01
      • 2021-06-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多