簡體   English   中英

如何在編譯時驗證模板 function 參數的類型

[英]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
  • 拋出異常
  • 返回一些錯誤代碼

由於以下原因,使用大小來檢查數據類型可能不是最佳方法:

  1. 不同的數據類型可以具有相同的大小,例如 float 和 int。

  2. 使用不同的數據類型並不總是意味着變量中包含的值是錯誤的。 例如,在您的情況下:

    內部數據 = 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM