繁体   English   中英

C ++根据模板参数值更改成员函数定义

[英]C++ Change member function definition based on template parameter value

是否可以基于模板参数的值在函数中有条件地编译语句? 例如:

template<typename T, bool chk>
class subject
{
public:
    // the ideal case    
    void doSomething(T new_val)
    {
        if(chk)
        {
          if(new_val != val)
              //do_something only if new_val is different from val
        }
        else
        {
            //do_something even if new_val and val are equal
        }
    }


    //or if that's not possible, if chk = 0 use this method
    void doSomething(T new_val) 
    {
        //do_something even if new_val and val are equal
    }

    // and if chk = 1 use this method
    void doSomething(T new_val) 
    {
        if(new_val != val)
           //do_something only if new_val is different from val
    }

    T val;
};

捕获是基于chk的值,我什至都不希望将if(new_val!=val)语句编译到函数中(因为使用的每个T类型都必须定义!=运算符)。

我猜这种方法的一个缺点是foo<int,0>foo<int,1>是不同的类,因此不可能定义一个不在乎chk是0还是1的函数(比如watch(foo<int>) )。

我正在查看的应用程序专门是观察者,对于某些类型,我只希望观察者在值实际更改时得到通知,对于其他类型,我希望观察者始终得到通知(对于那些我不希望的类型必须定义!=运算符)。

如果没有两个单独的类,这是否可能?

如果没有两个单独的类,这是否可能?

是的。 如果不想专门化您的类,以避免代码重复,则可以使用以下示例中的sfinae表达式:

#include <type_traits>
#include <iostream>

template<typename T, bool chk>
struct subject {
    template<bool trigger = chk>
    std::enable_if_t<trigger>
    doSomething(T new_val) {
        if(new_val != val) {
            std::cout << "new_val != val" << std::endl;
        } else {
            std::cout << "new_val == val" << std::endl;
        }
    }

    template<bool trigger = chk>
    std::enable_if_t<not trigger>
    doSomething(T new_val) {
        std::cout << "who cares?" << std::endl;
    }

    T val;
};

int main() {
    subject<int, true> s1{0};
    s1.doSomething(0);
    s1.doSomething(1);
    subject<int, false> s2{0};
    s2.doSomething(0);
    s2.doSomething(1);
}

这个想法是在编译时就为doSomething定义了正确的定义,它取决于模板参数chk的值。 另一个定义只是简单地按预期丢弃,根本无法使用。
请注意,要使sfinae表达式起作用, trigger模板参数必须是成员函数模板的实际参数。 这就是为什么您必须这样定义它的原因:

template<bool trigger = chk>
sfinae_expression_based_on_enable_if
doSomething(T new_val) { /* ... */ }

看到它在coliru上运行。

您正在寻找的被称为“模板专业化”。

您将必须专门化您的模板。 在定义了基本模板之后,如上所述,您将继续并定义其专业化:

template<typename T>
class subject<T, true>
{
public:

   // ...

然后,对于第二个模板参数为true (或false ,如果需要专门设置的话),您可以从头开始定义整个subject类,并进行所需的任何更改。 您可以删除,添加或完全更改它们。 专门的类可以具有不同的类成员,方法或相同的类方法,但是它们的工作方式完全不同。

重要的是要了解您正在定义整个类,而不仅仅是定义不同的位。 如果确实只需要对该类的一个较小方面进行专门化,那么这当然会导致一堆重复的代码; 因此通常需要对其进行重构,将不同的位放入帮助器类或函数中,并仅对不同的位进行专门化处理。

即将到来的C ++ 17标准还提供了一些其他的模板专业化替代方法。 但是在这种情况下,传统上,专业化是第一要学的东西。 因此,在继续学习C ++ 17的新知识之前,您应该将C ++书籍放到讨论模板专业化的章节中,并首先掌握其中的知识。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM