簡體   English   中英

將臨時結構作為模板參數傳遞

[英]Passing temporary struct as template argument

我正在創建一個矢量類,並試圖找出重用不同大小向量的最大代碼量的方法。 這是一個基本的例子:

template<typename T, unsigned int D>
class Vector
{
public:
    union {
        T v[D];
        struct {
            /* T x;
             * T y;
             * T z;
             * T w;
             */
        };
    };

    Vector()
    {
        for(unsigned int i=0; i<D; ++i)
            (*this)[i] = T(0);
    }
    Vector(T scalar)
    {
        for(unsigned int i=0; i<D; ++i)
            (*this)[i] = scalar;
    }

    inline T operator[](int i) { return (*this).v[i]; }
};

我希望成員變量可以公開訪問。 例如:

Vector<float,2> vec;
printf("X: %.2f, Y: %.2f\n", vec.x, vec.y);

我想做的是這樣的事情:

template<typename T>
class Vector2 : public Vector<T,2, struct { T x; T y; }> {};

template<typename T>
class Vector3 : public Vector<T,2, struct { T x; T y; T z; }> {};

並讓它覆蓋聯合中的結構:

template<typename T, unsigned int D, struct C>
class Vector
{
public:
    union {
        T v[D];
        // Place the passed struct here
    };
};

有沒有可行的方法呢? 如果可能的話,我不想使用標准庫以外的任何東西。 提前致謝。

編輯:在閱讀完所有答案后,我明白我使用工會的方式是不正確的! 感謝@MM指出這一點。 我已經選擇了不同的路線,但我選擇了最適合我當時尋找的答案。 再次感謝下面的所有歡迎回復!

你不想做什么。
無論如何,你可以這樣做:

template<typename T>
struct S { T x; T y; };

template<typename T>
class Vector2 : public Vector<T,2,S<T>> {};

或這個:

template<typename T>
class Vector2 : public Vector<T,2,S> {};

在第二種情況下, Vector可以定義為:

template<typename T, unsigned int D, template<typename> class S>
class Vector {
    using MyStruct = S<T>;

    // ...

    union {
        T v[D];
        MyStruct myStruct;
    };
};

它不能很好地擴展到大D ,但如果你只是在我想象的四到六個變體之后,你可以部分專門化一個基類:

#include <iostream>

template<typename T, size_t D>
struct VectorBase;

template<typename T>
struct VectorBase<T, 2>
{
    constexpr VectorBase() : v{} {}
    union {
        T v[2];
        struct { T x, y; };
    };
};

template<typename T>
struct VectorBase<T, 3>
{
    constexpr VectorBase() : v{} {}
    union {
        T v[3];
        struct { T x, y, z; };
    };
};

template<typename T>
struct VectorBase<T, 4>
{
    constexpr VectorBase() : v{} {}
    union {
        T v[4];
        struct { T x, y, z, w; };
    };
};

template<typename T, size_t D>
struct Vector : public VectorBase<T, D>
{
    using VectorBase<T, D>::v;
    using size_type = decltype(D);
    using value_type = T;

    constexpr Vector() : VectorBase<T,D>{} {}
    constexpr Vector(T scalar) {
        std::fill(std::begin(v), std::end(v), scalar);
    }

    constexpr T& operator[](size_type i) const noexcept { return v[i]; }
    constexpr const T& operator[](size_type i) noexcept { return v[i]; }

    constexpr size_type size() const noexcept { return D; }

    constexpr T* data() noexcept { return &v[0]; }
    constexpr const T* data() const noexcept { return &v[0]; }
};

template<typename T>
using Vector2 = Vector<T, 2>;
template<typename T>
using Vector3 = Vector<T, 3>;
template<typename T>
using Vector4 = Vector<T, 4>;

int main() {
    Vector3<int> v{1};

    std::cout << v[0] << ", " << v.z << "\n";
    return 0;
}

現場演示: http//ideone.com/T3QHoq

如果我理解正確你的主要目的是聲明與模板類的數組元素相對應的字段的順序。 您無法直接執行此操作,因為模板不接受內聯類型作為參數。 要解決此問題,您可以使用非類型模板參數將某些標簽綁定到數組的給定索引:

#include <cstdio>
#include <unordered_map>
#include <utility>

struct Label { } x, y, z, w;

template <Label&... labels>
struct Pack { };

template <class, class>
struct VectorParent;

template <Label&... labels, size_t... Is>
struct VectorParent<Pack<labels...>, std::index_sequence<Is...>> {
   static std::unordered_map<Label *, size_t> label_map;
};

template <Label&... labels, size_t... Is>
std::unordered_map<Label *, size_t> VectorParent<Pack<labels...>, std::index_sequence<Is...>>::label_map = {{&labels, Is}...};

struct LabelNotFound { };

template <class T, size_t N, Label&... labels>
struct Vector:VectorParent<Pack<labels...>, std::make_index_sequence<sizeof...(labels)>> {
   static_assert(N == sizeof...(labels),
       "the cound of labels should corespond to the number of elements of the vector");
   using VectorParent<Pack<labels...>, std::make_index_sequence<sizeof...(labels)>>::label_map;
   T t[N];
   T &operator->*(Label& l) {
      auto it = label_map.find(&l);
      if (it == label_map.end())
         throw LabelNotFound{};
      return t[it->second];
   }
};

int main() {
    Vector<float,2,x,y> vec;
    vec->*x = 10.0f;
    printf("X: %.2f, Y: %.2f\n", vec->*x, vec->*y); // prints: X: 10.00, Y: 0.00
    //vec->*w = 10.1f; //would throw an exception LabelNotFound
}

暫無
暫無

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

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