从模板类中的Bool值超载成员

Overloading members from template class on bool value

本文关键字:Bool 超载 成员      更新时间:2023-10-16

我正在尝试避免在项目的主分支上概念,因此我需要使用type_trait的某种替代方法:

我需要一个课程,其中一些功能会根据bool值而改变。

有人已经建议我分裂我的班级,但是在这里,这种情况是没有意义的。对于某些上下文,这是一个池,如果可以共享池的对象类型,则删除函数和其他一些都会更改。

所以我尝试使用std::enable_if,但是仍然有一些错误(我希望声明和实现是单独的)。

#include  <type_traits>
template < typename Object, bool Shared = false >
class Foo {
  template < bool S = Shared, typename std::enable_if<S>::type* = nullptr >
  void   bar();
  template < bool S = Shared, typename std::enable_if<!S>::type* = nullptr >
  void   bar();
};
template < typename Object,
           bool Shared >
template < bool S, typename std::enable_if<S>::type* = nullptr >
void   Foo<Object, Shared>::bar() {
    //do something
}

template < typename Object,
           bool Shared >
template < bool S, typename std::enable_if<!S>::type* = nullptr >
void   Foo<Object, Shared>::bar() {
  //do nothing
}
int main() {
  Foo<int> test;
  return 0;
}

Test3.cpp:16:33: error: default argument for template parameter for class enclosing ‘void Foo<Object, Shared>::bar()’
 void   Foo<Object, Shared>::bar() {
                                 ^
Test3.cpp:24:33: error: default argument for template parameter for class enclosing ‘void Foo<Object, Shared>::bar()’
 void   Foo<Object, Shared>::bar() {

编辑:删除复制/粘贴错误

1.应删除类名称的资格(即 Foo<Object, Shared>::),以删除成员函数声明内部类定义。

2.默认模板参数不允许用于成员模板的课外定义,只需删除它们。

不允许默认参数

  • 在会员模板的课外定义中(它们必须是 在班级主体内的声明中提供)

然后

template < typename Object, bool Shared = false >
class Foo {
  template < bool S = Shared, typename std::enable_if<S>::type* = nullptr >
  void  bar();
  template < bool S = Shared, typename std::enable_if<!S>::type* = nullptr >
  void  bar();
};
template < typename Object,
           bool Shared >
template < bool S, typename std::enable_if<S>::type*  >
void   Foo<Object, Shared>::bar() {
    //do something
}
template < typename Object,
           bool Shared >
template < bool S, typename std::enable_if<!S>::type* >
void   Foo<Object, Shared>::bar() {
  //do nothing
}

live

作为替代方案,您可以使用标签dispatching:

template <typename Object, bool Shared = false>
class Foo {
public:
    void bar() { bar(std::integral_constant<bool, Shared>{}); }
private:
    void bar(std::true_type);
    void bar(std::false_type);
};
template <typename Object, bool Shared>
void Foo<Object, Shared>::bar(std::true_type) { /**/ }
template <typename Object, bool Shared>
void Foo<Object, Shared>::bar(std::false_type) { /**/ }

自C 17以来,您可以使用if constexpr

template <typename Object, bool Shared = false>
class Foo {
public:
    void bar() {
        if constexpr (Shared) {
            // ...
        } else {
            // ...
        }
    }

因此,每个块仅在正确的版本中可用:

  • 所以没有运行时分支(我希望无论如何在您的情况下都可以优化常规分支)
  • 未选择的块可能只有在选择该分支的情况下才有有效的代码(当它取决于> type >)。

和C 20引入requires

template <typename Object, bool Shared = false>
class Foo {
public:
    void bar() requires(Shared) {
        // ...
    }
    void bar() requires(!Shared) {
        // ...
    }
};

这是您的代码修复后(最小,工作示例):

#include  <type_traits>
#include <iostream>
template < typename Object, bool Shared = false >
class Foo {
public:
    template < bool S = Shared, typename std::enable_if<S>::type* = nullptr >
    void bar();
    template < bool S = Shared, typename std::enable_if<!S>::type* = nullptr >
    void bar();
};
template < typename Object, bool Shared >
template < bool S, typename std::enable_if<S>::type*>
void  Foo<Object, Shared>::bar() {
    std::cout << "do something" << std::endl;
}
template < typename Object, bool Shared >
template < bool S, typename std::enable_if<!S>::type*>
void Foo<Object, Shared>::bar() {
    std::cout << "do nothing" << std::endl;
}
int main() {
    Foo<int> test;
    test.bar<>();
    test.bar<true>();
    return 0;
}

这是一个额外的限定符和默认参数的问题

作为额外的注意,这是一个更干净的解决方案:

#include <type_traits>
#include <iostream>
template<bool b>
using allow_if = typename std::enable_if<b>::type;
template <typename Object, bool Shared = false>
class Foo {
public:
    template<bool S = Shared>
    allow_if<S> bar();
    template<bool S = Shared>
    allow_if<!S> bar();
};
template<typename Object, bool Shared>
template<bool S>
allow_if<S> Foo<Object, Shared>::bar() {
    std::cout << "do something" << std::endl;
}
template<typename Object, bool Shared>
template<bool S>
allow_if<!S> Foo<Object, Shared>::bar() {
    std::cout << "do nothing" << std::endl;
}
int main() {
    Foo<int> test;
    test.bar<>();
    test.bar<true>();
    return 0;
}