[英]Specialize member functions based on size of member container
I have a class that holds some statically-sized containers: 我有一个类,它包含一些静态大小的容器:
template <typename Container>
struct Point {
Container container;
...
void bar();
}
where a Container
class might look like: Container
类可能如下所示:
struct Container1 {
static constexpr size_t size = 5;
}
Now I want to specialize the bar
method based on the size of the container. 现在我想根据容器的大小来专门化
bar
方法。 I do not understand how to do that. 我不明白该怎么做。
EDIT: 编辑:
I would like a C++11 solution. 我想要一个C ++ 11解决方案。 C++14 might work, but the compilers we work with typically have spotty C++14 support.
C ++ 14可能有用,但我们使用的编译器通常具有不稳定的C ++ 14支持。
EDIT: 编辑:
Stack Danny suggested a solution which compiles with Clang, but not with GCC. Stack Danny提出了一个解决方案,它与Clang编译,但不与GCC编译。
Instead of specialisation, use SFINAE 而不是专业化,使用SFINAE
template <typename Container>
class Point {
Container container;
template<size_t S> std::enable_if_t<S==3>
bar_t() { std::cout << "specialisation for size=3\n"; }
template<size_t S> std::enable_if_t<S==5>
bar_t() { std::cout << "specialisation for size=5\n"; }
template<size_t S> std::enable_if_t<S==42>
bar_t() { std::cout << "specialisation for size=42\n"; }
public:
void bar()
{ bar_t<Container::size>(); }
};
std::enable_if_t
is C++14, but you can trivially declare it yourself: std::enable_if_t
是C ++ 14,但你可以自己简单地声明它:
#if __cplusplus < 201402L
template<bool C, typename T=void>
using enable_if_t = typename enable_if<C,T>::type;
#endif
Btw, your question smells like an XY problem : do you really need to specialize bar()
for the Container::size
? 顺便说一句,你的问题有点像XY问题 :你真的需要为
Container::size
专门化bar()
吗? In the following example, a loop is unrolled for any size N
. 在以下示例中,为任何大小
N
展开循环。
template<typename scalar, size_t N>
class point // a point in R^N
{
scalar array[N];
public:
// multiplication with scalar
point& operator*=(scalar x) noexcept
{
// unroll loop using template meta programming
loop([array,x](size_t i) { array[i] *= x; };);
/* alternatively: rely on the compiler to do it
for(size_t i=0; i!=N; ++i)
array[i] *= x;
*/
return *this;
}
private:
template<size_t I=0, typename Lambda>
static enable_if_t<(I<N)> loop(Lambda &&lambda)
{
lambda(I);
loop<I+1>(lambda);
}
template<size_t I=0, typename Lambda>
static enable_if_t<(I>=N)> loop(Lambda &&) {}
};
It is called template specialization and works as follows: 它被称为模板专业化,其工作原理如下:
#include <cstdint>
#include <iostream>
struct Container1 {
static constexpr size_t size = 5;
};
struct Container2 {
static constexpr size_t size = 3;
};
template <typename Container>
struct Point {
Container container;
void bar() {
this->bar_templated<Container::size>();
}
private:
template<std::size_t size>
void bar_templated() {
std::cout << "default\n";
}
template<>
void bar_templated<3>() {
std::cout << "specialized <3>\n";
}
template<>
void bar_templated<5>() {
std::cout << "specialized <5>\n";
}
};
int main(){
Point<Container1> p1;
p1.bar();
Point<Container2> p2;
p2.bar();
}
output 产量
specialized <5>
specialized <3>
due to bug 85282 in gcc making it impossible to compile an explicit specialization in non-namespace scope (thanks @songyuanyao), there are errors: 由于gcc中的bug 85282使得无法在非命名空间范围内编译显式特化 (感谢@songyuanyao),因此存在错误:
25:14: error: explicit specialization in non-namespace scope 'struct Point'
25:14:错误:非命名空间范围'struct Point'中的显式特化
26:27: error: template-id 'bar_templated<3>' in declaration of primary template
26:27:错误:主模板声明中的template-id'bar_templated <3>'
...
...
30:10: error: 'void Point::bar_templated()' cannot be overloaded
30:10:错误:'void Point :: bar_templated()'无法重载
But you can workaround this by moving the functions out of the class and still achieve specialization: 但是你可以通过将函数移出类并仍然实现特化来解决这个问题:
template<std::size_t size>
void bar_templated() {
std::cout << "default\n";
}
template<>
void bar_templated<3>() {
std::cout << "specialized 3\n";
}
template<>
void bar_templated<5>() {
std::cout << "specialized 5\n";
}
template <typename Container>
struct Point {
Container container;
void bar() {
bar_templated<Container::size>();
}
};
This way the functions are public, which may not be what you want, though. 这样,函数是公共的,但可能不是你想要的。 Well, if you're writing inside a header file you could define them inside an anonymous namespace.
好吧,如果你在头文件中写入,你可以在匿名命名空间内定义它们。
Also: if constexpr - but that's only C++17 and forward. 另外: 如果constexpr - 但那只是C ++ 17和前进。 It reducing the code size by alot and keeping it's logical nature makes it the best approach here, for sure.
它确实减少代码大小并保持其逻辑性质使其成为最佳方法。
void bar() {
if constexpr (Container::size == 3) {
std::cout << "specialized <3>\n";
}
else if constexpr (Container::size == 5) {
std::cout << "specialized <5>\n";
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.