簡體   English   中英

可以根據c ++中的模板args更改類成員嗎

[英]Can the class member can be changed depending on the template args in c++

我希望可以根據模板參數更改類成員。 我想要類似的東西

template<int value>
class MyClass
{
public:
   void print()
   {
      // using the member
      std::cout << sizeData() << std::endl;
      for (int i=0;i<sizeData();i++)
      {
         std:cout << data[i] << std::endl;
      }
   }
   static int sizeData()
   {
     #if value == 1
        return 3;
     #endif
     #if value == 2
        return 6;
     #endif
   }
   static int sizeArray()
   {
     #if value == 1
        return 40;
     #endif
     #if value == 2
        return 200;
     #endif
   }
private:
   #if value == 1
      int data[3];
      const static int array[40];
   #endif
   #if value == 2
      int data[6];
      const static int array[200];
   #endif
}

不知道能不能用c++實現。

謝謝你的時間。

添加

許多先生已經在 C++11 和 C++17 中給出了答案。 謝謝你的所有建議。

如果代碼能用C++98解決就完美了。 因為我的代碼應該在只支持 C++98 的平台上運行。

您可以使用std::conditional來選擇您想要的成員

template<int value>
class MyClass
{
public:
   static int sizeData()
   {
       return (value == 1) ? 3 : 6; // needs to be improved
   }
   static int sizeArray()
   {
       return sizeof(array) / sizeof(array[0]);  // size of array divided by size of element is then number of elements in the array
   }
private:

   std::conditional_t<value == 1, int[3], int[6]> data;
   const static std::conditional_t<value == 1, int[40], int[200]> array;

};

盡管std::conditional不是 C++98 的一部分,但它僅使用 C++98 C++ 實現,因此您可以使用參考站點鏈接中的可能實現來實現自己。 你可以看到與

#include <iostream>

template<bool B, class T, class F>
struct conditional { typedef T type; };
 
template<class T, class F>
struct conditional<false, T, F> { typedef F type; };

template<int value>
class MyClass
{
public:
    static int sizeData()
    {
       return (value == 1) ? 3 : 6; // needs to be improved
    }
    static int sizeArray()
    {
       return sizeof(array) / sizeof(array[0]);
    }
private:

    typename conditional<value == 1, int[3], int[6]>::type data;
    const static typename conditional<value == 1, int[40], int[200]>::type array;

};

int main()
{
    MyClass<1> m;
    std::cout << m.sizeData();
}

在這個活生生的例子中


這種類型的sizeData會崩潰,因為data不是static但函數是static的。 為了避免代碼重復,我們可以使用 enum 技巧來獲取數組大小的編譯時常量,而不是使用std::conditional ,並使用類似的方法

#include <iostream>

template<int value>
class MyClass
{
public:
    static int sizeData()
    {
       return data_size; // now improved
    }
    static int sizeArray()
    {
       return array_size;
    }
private:
    enum { data_size = (value == 1) ? 3 : 6 }; // this is required to be a compile time constant
    enum { array_size = (value == 1) ? 40 : 200 }; // these need to become before the array members
    int data[data_size]; // less verbose
    const static int array[array_size];
};

int main()
{
    MyClass<1> m;
    std::cout << m.sizeData();
}
    
    

您需要將條件邏輯移動到本地化的位置。 如果 C++17 是一個選項, static inline constexpr變量是您的朋友:

template<int value>
class MyClass
{
private:
   inline static constexpr int data_size = (value == 1) ? 3 : 6;
   inline static constexpr int array_size = (value == 1) ? 40 : 200;

public:
   static int sizeData() { return data_size; }
   static int sizeArray() {return array_size; }

private:
      int data[data_size];
      const static int array[array_size];  
};

如果計算大小的邏輯需要更復雜,你總是可以編寫一個constexpr函數來計算它給定一個value作為(非模板)參數。

由於您處理 C++98,因此您必須使用模板專業化

template<int value>
class MyClass
{
};

template<>
class MyClass<1>
{
public:
   int sizeData()
   {
       return 3;
   }

   int sizeArray()
   {
       return 40;
   }
private:
   int data[3];
   const static int array[40];
};

template<>
class MyClass<2>
{
public:
   int sizeData()
   {
       return 6;
   }

   int sizeArray()
   {
       return 200;
   }
private:
   int data[6];
   const static int array[200];
};

template<int value>
class Child : public MyClass<value>
{
public:
    int calc()
    {
        // will only work and compile for value 1, 2
        return this->sizeData() + this->sizeArray();
    }
};

您可以使用if constexpr並立即計算constexpr lambdas

免責聲明:它只是 C++ 17,需要額外的括號括住 lambda 才能編譯,我真的不建議按原樣使用此代碼。 它的目的只是演示

template<int value>
class MyClass
{
public:
   static int sizeData()
   {
     if constexpr(value == 1)
        return 3;
     
     if constexpr (value == 2)
        return 6;     
   }
   static int sizeArray()
   {
     if constexpr (value == 1)
        return 40;
     
     if constexpr (value == 2)
        return 200;
   }
private:
    int data[([](int v) constexpr { if (v == 1) return 3; if (v==2) return 6; }(value))];
    const static int array[([](int v) constexpr { if (v == 1) return 40; if (v==2) return 200; }(value))]; 
};

int main()
{
   MyClass<1> m1;
   MyClass<2> m2;
}

從 C++17 開始,您可以使用constexpr if

template<int value>
class MyClass
{
public:
    MyClass() : data() {}

    static constexpr int sizeData() {
        if constexpr (value == 1) { return 3; }
        else if constexpr (value == 2) { return 6; }
        else { return 1; } // default value is '1'
    }
    
    static constexpr int sizeArray() {
        if constexpr (value == 1) { return 40; }
        else if constexpr (value == 2) { return 200; }
        else { return 10; } // default value is '10'
    }
private:
   int data[sizeData()];
   const static int array[sizeArray()];
};

如果使用例如 C++14,您可以實現自定義值特征,在編譯時將給定的int值映射到另一個命名 ( int ) 常量,並在類模板中使用這些值特征:

template<int value>
constexpr int ValueToDataSizeMapping = 1; // default is '1'

template<>
constexpr int ValueToDataSizeMapping<1> = 3;

template<>
constexpr int ValueToDataSizeMapping<2> = 6;

template<int value>
constexpr int ValueToArraySizeMapping = 10; // default is '10'

template<>
constexpr int ValueToArraySizeMapping<1> = 40;

template<>
constexpr int ValueToArraySizeMapping<2> = 200;

template<int value>
class MyClass
{
public:
    MyClass() : data() {}
private:
   int data[ValueToDataSizeMapping<value>];
   const static int array[ValueToArraySizeMapping<value>];
};

不,這不能在 C++ 中實現。 預編譯器“if”可以通過運行時變量進行評估。

您可以聲明一個std::vector來解決這個問題。 通過這種方式,您可以使用作為參數傳遞的值對其進行初始化。

此時大小數組和大小數據函數不需要預編譯器“if”,只需要簡單的if-else語句即可。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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