![](/img/trans.png)
[英]is there a way to put condition on constant value parameter in C++ template specialization?
[英]C++ Template Specialization with Constant Value
给定一个模板参数的数值常量,是否有一种直接的方法来定义C ++模板类的部分特化? 我正在尝试为特定类型的模板组合创建特殊构造函数:
template <typename A, size_t B> class Example
{
public:
Example() { };
A value[B];
};
template <typename A, 2> class Example
{
public:
Example(b1, b2) { value[0] = b1; value[1] = b2; };
};
此示例将无法编译,在第二个定义中的Expected identifier before numeric constant
返回错误Expected identifier before numeric constant
。
我已经看过这里和其他地方的一些例子,但大多数似乎都围绕着一个类型而不是一个常量。
编辑:
寻找一种编写有条件使用的构造函数的方法,其功能如下:
template <typename A, size_t B> class Example
{
public:
// Default constructor
Example() { };
// Specialized constructor for two values
Example<A,2>(A b1, A b2) { value[0] = b1; value[1] = b2; };
A foo() {
A r;
for (size_t i = 0; i < b; ++b)
r += value[i];
return r;
}
// Hypothetical specialized implementation
A foo<A, 2>() {
return value[0] + value[1];
}
A value[B];
};
您需要将专业化放在正确的位置:
template <typename A> class Example<A,2>
如果要创建子类:
template <typename A> class ExampleSpecialization : public Example<A,2>
专门用于typedef的行为类似于专门用于整数参数的行为。
我认为这可能有效:
#include <iostream>
template <typename A, size_t B>
class Example {
public:
Example()
{
Construct<B>(identity<A, B>());
}
A foo()
{
return foo<B>(identity<A, B>());
}
private:
template <typename A, size_t B>
struct identity {};
template <size_t B>
void Construct(identity<A, B> id)
{
for (size_t i = 0; i < B; ++i)
{
value[i] = 0;
}
std::cout << "default constructor\n";
}
template <size_t B>
void Construct(identity<A, 2> id)
{
value[0] = 0;
value[1] = 0;
std::cout << "special constructor\n";
}
template <size_t B>
A foo(identity<A, B> id)
{
A r = 0;
for (size_t i = 0; i < B; ++i)
{
r += value[i];
}
std::cout << "default foo\n";
return r;
}
template <size_t B>
A foo(identity<A, 2> id)
{
std::cout << "special foo\n";
return value[0] + value[1];
}
A value[B];
};
int main()
{
Example<int, 2> example; // change the 2 to see the difference
int n = example.foo();
std::cin.get();
return 0;
}
对不起,我只是从我的测试项目中复制并粘贴它。 它在某种程度上并不是真正的“专业化”,它只是调用专用函数的重载。 我不确定这是不是你想要的,因为这不是很优雅。
如果内存服务,它应该更像:
template <typename A, size_t B> class Example
{
public:
Example() { };
A value[B];
};
template <typename A> class Example<A, 2>
{
public:
Example(A b1, A b2) { value[0] = b1; value[1] = b2; };
};
我不认为这是非常允许的 - 在专门版本中没有定义b1
和/或b2
的类型。
编辑[基于已编辑的问题]:是的,模板专精化会产生一种与其专用基础无关的新类型。 特别是,两者不共享任何实现。 您不能(通过专门化类模板)生成使用两个不同ctors之一的单一类型,具体取决于非类型参数的值。
你可以尝试这样的事情:
template<size_t s>
struct SizeTToType { static const size_t value = s; };
template<bool> struct StaticAssertStruct;
template<> struct StaticAssertStruct<true> {};
#define STATIC_ASSERT(val, msg) { StaticAssertStruct<((val) != 0)> ERROR_##msg; (void)ERROR_##msg;}
template <typename A, size_t B>
class Example
{
public:
Example() { };
Example(A b1){ value[0] = b1; }
Example(A b1, A b2) {
STATIC_ASSERT(B >= 2, B_must_me_ge_2);
value[0] = b1; value[1] = b2;
}
A foo() { return in_foo(SizeTToType<B>()); }
protected:
template<size_t C>
A in_foo(SizeTToType<C>) {
cout << "univ" << endl;
A r;
for (size_t i = 0; i < B; ++i)
r += value[i];
return r;
}
A in_foo(SizeTToType<2>){
cout << "spec" << endl;
return value[0] + value[1];
}
A value[B];
};
http://www.ideone.com/wDcL7上的工作示例
在模板中,如果你不使用方法,它将不会存在于编译的代码中,所以这个解决方案不应该使可执行文件更大,因为ctors你不能使用某些专门的类(例如Example<int, 1>
不应该有Example(A b1, A b2)
ctor)。
如果您的目标是只需要覆盖专业化中的一些方法/构造函数,那么可以考虑使用通用基类来保存所有Example
模板的通用实现,这样您就不必在每个专门化中重写它用。
例如:
template < typename A, size_t B >
class ExampleGeneric {
public:
// generic implementation of foo inherited by all Example<A,B> classes
void foo() {
A r;
for (size_t i = 0; i < B; ++i)
r += value[i];
return r;
}
// generic implementation of bar inherited by all Example<A,B> classes
void bar() {
A r;
for (size_t i = 0; i < B; ++i)
r *= value[i];
return r;
}
A values[B];
};
template < typename A, size_t B >
class Example : public ExampleGeneric<A,B> {
public:
//default to generic implementation in the general case by not overriding anything
};
//*** specialization for 2
template < typename A >
class Example<A,2> : public ExampleGeneric<A,2>{
public:
// has to be provided if you still want default construction
Example() {
}
//extra constructor for 2 parameters
Example( A a1, A a2 ) {
values[0] = a1;
values[1] = a2;
}
// specialization of foo
void foo() {
return values[0] + values[1];
}
// don't override bar to keep generic version
};
#include <iostream>
using namespace std;
template<typename _T, size_t S>
class myclass {
_T elem[S];
public:
myclass() {
for (int i = 0; i < S; i++) {
elem[i] = i;
}
}
void Print() {
for (int i = 0; i < S; i++) {
cout << "elem[" << i << "] = " << elem[i] << endl;
}
}
};
int main(int argc, char **argv)
{
myclass < int, 10 > nums;
nums.Print();
myclass < int, 22 > nums1;
nums1.Print();
}
这适用于我的linux机器
g ++(GCC)4.1.2 20080704(Red Hat 4.1.2-48)版权所有(C)2006 Free Software Foundation,Inc。这是免费软件; 查看复制条件的来源。 没有保修; 甚至不适用于适销性或特定用途的适用性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.