C++ “专业化”;类型参数";加上;“非类型参数”;(或者反过来说)
下面的玩具示例演示了我想要实现的目标C++ “专业化”;类型参数";加上;“非类型参数”;(或者反过来说),c++,templates,partial-specialization,C++,Templates,Partial Specialization,下面的玩具示例演示了我想要实现的目标 #include <cstddef> template<size_t ElementSize> class Buffer { public: char buffer[ElementSize]; }; template<typename T> class Buffer<sizeof(T)> { public: char buffer[sizeof(T)]; }; int main() {
#include <cstddef>
template<size_t ElementSize>
class Buffer
{
public:
char buffer[ElementSize];
};
template<typename T>
class Buffer<sizeof(T)>
{
public:
char buffer[sizeof(T)];
};
int main()
{
Buffer<4> b1; // buffer with 4 bytes
Buffer<int> b2; // buffer with space for "int"
}
#包括
模板
类缓冲区
{
公众:
字符缓冲区[ElementSize];
};
模板
类缓冲区
{
公众:
字符缓冲区[sizeof(T)];
};
int main()
{
缓冲区b1;//具有4个字节的缓冲区
Buffer b2;//带“int”空格的缓冲区
}
这段代码显然无法编译:
$ g++ test.cpp
test.cpp:12:7: error: template argument ‘sizeof (T)’ involves template parameter(s)
class Buffer<sizeof(T)>
^
test.cpp: In function ‘int main()’:
test.cpp:22:12: error: type/value mismatch at argument 1 in template parameter list for ‘template<long unsigned int ElementSize> class Buffer’
Buffer<int> b2; // buffer with space for "int"
^
test.cpp:22:12: error: expected a constant of type ‘long unsigned int’, got ‘int’
test.cpp:22:16: error: invalid type in declaration before ‘;’ token
Buffer<int> b2; // buffer with space for "int"
$g++test.cpp
test.cpp:12:7:错误:模板参数“sizeof(T)”涉及模板参数
类缓冲区
^
test.cpp:在函数“int main()”中:
test.cpp:22:12:错误:“模板类缓冲区”的模板参数列表中参数1的类型/值不匹配
缓冲区b2;//带“int”空格的缓冲区
^
test.cpp:22:12:错误:应为“long unsigned int”类型的常量,但得到了“int”
test.cpp:22:16:错误:在“;”之前的声明中的类型无效代币
缓冲区b2;//带“int”空格的缓冲区
我有没有办法对这样的模板进行两种专门化?一种是使用以字节为单位的显式大小(非类型参数),另一种是从类型T
(类型参数)中获取大小(使用sizeof()
)?我感兴趣的是一种解决方案,它不需要两个具有不同名称的单独模板或任何#define
宏
我试图以“反向”的方式实现这一点——将
作为主模板,使用size\u t
作为专门化(将char[sizeof(t)]
或std::aligned\u storage::type
传递到主模板),但这也失败了。。一旦我们有了模板类缓冲区
,就专业化而言,我们所能做的非常有限。即§14.5.5/8.1:
部分专用的非类型参数表达式不应包含
部分专门化,除非参数表达式是简单标识符。[示例:
类模板不能重载。如果类模板
Buffer
采用类型size\u t
的非类型参数,则每次编写Buffer
时,对象必须是有效的非类型参数;它不能是类型。反之亦然-如果Buffer
采用类型参数,则每个tim你写的东西一定是一种类型
部分专门化的模板参数总是在部分专门化匹配过程中推导出来的;您永远不能显式地指定它们
但是,函数模板可以重载。因此,您可以编写重载make_buffer
s并使用auto
:
template<class T> Buffer<sizeof(T)> make_buffer() { return {}; }
template<size_t Size> Buffer<Size> make_buffer() { return {}; }
auto buffer1 = make_buffer<int>();
auto buffer2 = make_buffer<42>();
然后你可以很容易地为此编写一个宏。我对这个答案不感兴趣。必须有更好的方法从标准中解释这一点,我就是找不到。
template <size_t I> class Buffer<I> { .. };
template <size_t ElementSize>
class Buffer {
char buffer[ElementSize];
};
template <typename T>
using BufferFromType = Buffer<sizeof(T)>;
// or, if not C++11, another type
template <typename T>
class BufferFromType : public Buffer<sizeof(T)> { };
template<class T> Buffer<sizeof(T)> make_buffer() { return {}; }
template<size_t Size> Buffer<Size> make_buffer() { return {}; }
auto buffer1 = make_buffer<int>();
auto buffer2 = make_buffer<42>();
decltype(make_buffer<int>()) buffer1;
decltype(make_buffer<42>()) buffer2;