C ++基于模板参数值更改成员函数定义

时间:2017-03-05 02:12:45

标签: c++ c++11 templates

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

localStorage

catch是基于chk的值我甚至不希望将语句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; }; 编译到函数中(因为那时使用的每个类型T都必须定义一个!=运算符)。

我想这种方法的一个缺点是if(new_val!=val)foo<int,0>是不同的类,所以不可能定义一个不关心chk是0还是1的函数(比如说foo<int,1>)。

我正在特别关注的应用程序是一个观察者,对于某些类型我只希望观察者在值实际发生变化时得到通知,对于其他类型我希望观察者始终得到通知(对于那些类型我不喜欢我不想要定义一个!=运算符。

这可能没有两个单独的课程吗?

2 个答案:

答案 0 :(得分:2)

  

这可能没有两个单独的课程吗?

是的,确实如此。如果您不想专门化您的课程,以避免代码重复,您可以使用类似以下示例中的表达式:

#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上运行时看到它。

答案 1 :(得分:0)

您正在寻找的是模板专业化&#39;。

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

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

   // ...

然后继续从头开始定义整个subject类,进行所需的任何更改,对于第二个模板参数为true(或false的情况,如果是&# 39;你需要专业的东西)。您可以删除内容,添加内容或完全更改内容。专业类可以有不同的类成员,方法或相同的类方法,但它们的工作方式完全不同。

重要的是要了解您现在正在定义整个类,而不仅仅是不同的位。如果该类只有一个次要方面确实需要专门化,那么当然会产生一堆重复的代码;所以通常需要重构它,将变化的位放入辅助类或函数中,并专门处理变化的位。

即将推出的C ++ 17标准还有其他一些模板专业化的替代方案;但是,对于这些情况,专业化传统上是人们学习的第一件事。因此,你应该打开你的C ++书籍到讨论模板专业化的章节,并在开始使用C ++ 17中的新东西之前先获得好处。

相关问题