[英]How can I validate the type of a template function argument at compile time
我正在寫一個 class 來傳遞傳感器數據,我想這樣做是為了讓 class 的用戶不能使用不正確的數據類型來發送傳感器數據。
我想像這樣設置我的 class:
private:
static const _sensor_bytes[] = {2, 4, ...};
public:
enum sensor_name_t {
SENSOR1 = 0,
SENSOR2 = 1,
...
};
template<class T>
void writeData(sensor_name_t sensor, T data){
if _sensor_bytes[sensor] != sizeof(T){
// Do not compile
}
}
例如,
int data = 30;
writeData(SENSOR1, data); // This would not compile because _sensor_bytes[0] = 2 and sizeof(int) = 4
writeData(SENSOR2, data); // This would compile because _sensor_bytes[1] = 4 and sizeof(int) = 4
我是否以正確的方式解決這個問題? 如果是這樣,我將如何實現此功能?
您不能使用 function void writeData(sensor_name_t sensor, T data)
執行此操作,因為sensor
的值在運行時已知,因此無法在編譯時驗證並引發錯誤。
變體 1
您可以嘗試使用std::enable_if
,將sensor
從 function 參數移至模板參數,並將constexpr
用於_sensor_bytes
。 它需要編譯器支持 C++11。
#include <cstdint>
#include <type_traits>
class Test {
private:
static constexpr int _sensor_bytes[] = {2, 4};
public:
enum sensor_name_t {
SENSOR1 = 0,
SENSOR2 = 1
};
template<int sensor,
class T,
typename = typename std::enable_if<(sizeof(T) == _sensor_bytes[sensor])>::type >
void writeData(T data) {
// Use 'sensor' and 'data' here
// ...
}
};
int main()
{
Test test;
uint16_t data1;
uint32_t data2;
test.writeData<Test::SENSOR1>(data1);
test.writeData<Test::SENSOR2>(data2);
//test.writeData<Test::SENSOR2>(data1); // Will not compile
//test.writeData<Test::SENSOR1>(data2); // Will not compile
return 0;
}
變體 2
如果您仍然需要在運行時傳遞兩個function 參數,那么也應該在運行時進行驗證:
assert
由於以下原因,使用大小來檢查數據類型可能不是最佳方法:
不同的數據類型可以具有相同的大小,例如 float 和 int。
使用不同的數據類型並不總是意味着變量中包含的值是錯誤的。 例如,在您的情況下:
內部數據 = 30; 寫入數據(傳感器 1,數據); // 這不會編譯,因為 _sensor_bytes[0] = 2 和 sizeof(int) = 4
值 30 可以存儲在 2 個字節中,所以你真的要在這里拋出編譯錯誤嗎? 但是,這純粹是特定於實現的。
在編譯時驗證模板 function 參數類型的一種方法是初始化一個虛擬變量。 下面是一個例子:
enum sensor_name_t {
SENSOR1 = 0,
SENSOR2 = 1
};
int sensor1;
std::string sensor2;
template<class T>
void writeData(sensor_name_t sensor, T data){
switch(sensor)
{
case SENSOR1:
{
int temp = data; // you know that sensor1 is of type int
// do your stuff
}
break;
case SENSOR2:
{
std::string temp = data; // you know that sensor2 is of type string
// do your stuff
}
break;
default:
break;
}
}
int main()
{
sensor1 = 30;
writeData(SENSOR1, sensor1);
writeData(SENSOR2, sensor1);
}
上面的代碼片段會產生以下編譯時錯誤:
錯誤:請求從“int”到非標量類型“std::string”{又名“std::__cxx11::basic_string”}的轉換
上面的邏輯可以用更優雅的方式實現。 你可以在這里得到一些想法
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.