在 bool 值上重载模板 class 中的成员
Overloading members from template class on bool value
我试图避免在我的项目的 master 分支上使用概念,所以我需要某种替代方法 type_trait
:
我需要一个class,一些功能会根据bool
值而改变。
有人已经建议我拆分我的 class,但这种情况在这里没有意义。对于某些上下文,它是一个池,其中删除函数和一些其他函数将根据池的对象类型是否可以共享而改变。
所以我尝试使用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() {
编辑:删除了 copy/paste 错误
1.The class 名称(即Foo<Object, Shared>::
)的限定应删除成员函数声明 inside class定义。
2.Default template arguments 不允许超出class 成员模板定义,只需删除它们。
Default parameters are not allowed
- in the out-of-class definition of a member template (they have to be
provided in the declaration inside the class body)
然后
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
}
这是您修复后的代码(最小的工作示例):
#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;
}
这是一个额外限定符和默认参数的问题,不能在 class 定义中重复。
另外请注意,这是一个更简洁的解决方案:
#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;
}
作为替代方案,您可以使用标签调度:
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 {
// ...
}
}
因此每个块仅在正确的版本中可用:
- 所以没有运行时分支(我希望常规分支在你的情况下得到优化)
- 未选择的块可能包含仅当该分支被选择时才有效的代码(当它取决于 类型 时最有用)。
并且C++20引入了requires
:
template <typename Object, bool Shared = false>
class Foo {
public:
void bar() requires(Shared) {
// ...
}
void bar() requires(!Shared) {
// ...
}
};
我试图避免在我的项目的 master 分支上使用概念,所以我需要某种替代方法 type_trait
:
我需要一个class,一些功能会根据bool
值而改变。
有人已经建议我拆分我的 class,但这种情况在这里没有意义。对于某些上下文,它是一个池,其中删除函数和一些其他函数将根据池的对象类型是否可以共享而改变。
所以我尝试使用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() {
编辑:删除了 copy/paste 错误
1.The class 名称(即Foo<Object, Shared>::
)的限定应删除成员函数声明 inside class定义。
2.Default template arguments 不允许超出class 成员模板定义,只需删除它们。
Default parameters are not allowed
- in the out-of-class definition of a member template (they have to be provided in the declaration inside the class body)
然后
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
}
这是您修复后的代码(最小的工作示例):
#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;
}
这是一个额外限定符和默认参数的问题,不能在 class 定义中重复。
另外请注意,这是一个更简洁的解决方案:
#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;
}
作为替代方案,您可以使用标签调度:
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 {
// ...
}
}
因此每个块仅在正确的版本中可用:
- 所以没有运行时分支(我希望常规分支在你的情况下得到优化)
- 未选择的块可能包含仅当该分支被选择时才有效的代码(当它取决于 类型 时最有用)。
并且C++20引入了requires
:
template <typename Object, bool Shared = false>
class Foo {
public:
void bar() requires(Shared) {
// ...
}
void bar() requires(!Shared) {
// ...
}
};