只有条件的C ++模板

时间:2018-12-16 23:12:12

标签: c++ templates conditional

所以说我有一个数组包装器:

template <const size_t i,typename T>
class ArrayWrapper {
    T arr [i] = {0};
public:
    //constructors and operators like [] ...
    void operator=(ArrayWrapper<i,T> & arrIn){
            for (size_t k =0; k< i;k++){
                arr[k] = arrIn[k];
            }
        }
};

现在,我希望能够将数组分配给其他数组,例如:

ArrayWrapper<2> arr1({1,2,3});
ArrayWrapper<2> arr2() = arr1;

但是现在我希望能够将较短的数组分配给较长的数组:

ArrayWrapper<3> arr1({1,2,3});
ArrayWrapper<4> arr2() = arr1;

此处arr2 = {1,2,3,0} 但这反过来没有道理。

ArrayWrapper<3> arr1({1,2,3});
ArrayWrapper<2> arr2() = arr1;

由于我们在这里丢失信息 那么如何告诉编译器不允许j> i重载呢?

{...in ArrayWrapper class
    template <size_t j> 
        void operator=(ArrayWrapper<j,T> & arrIn){
                for (size_t k =0; k< j;k++){
                    arr[k] = arrIn[k];
                }
            }
...}

我尝试过:

template <size_t std::enable_if< j<=i>::j>
void operator=(ArrayWrapper<j,T> & arrIn){
        for (size_t k =0; k< j;k++){
            arr[k] = arrIn[k];
        }
    }

但是编译器讨厌它;(

3 个答案:

答案 0 :(得分:3)

我只在这里使用static_assert。由于ij在编译时是已知的,因此您可以使用

template <size_t j> 
void operator=(ArrayWrapper<j,T> & arrIn)
{
    static_assert(i >= j, "Assigning a larger ArrayWrapper to a smaller ArrayWrapper is not allowed");
    for (size_t k =0; k< j;k++){
        arr[k] = arrIn[k];
    }
}

现在,不仅代码无法编译,而且您收到一条非常好的错误消息。

答案 1 :(得分:0)

这是一个根据this关于模板转换的帖子改编的工作示例:

#include <iostream>
#include <initializer_list>
template < const size_t i, typename T >
class ArrayWrapper {
public:
    T arr[i] = { 0 };
    ArrayWrapper<i,T>(){ }
    ArrayWrapper<i,T>(std::initializer_list<const size_t> arrIn) {
        std::copy(arrIn.begin(), arrIn.end(), arr);
    }
    void copyArr(T *arr, T *arrIn) {
        for (size_t k = 0; k < i; k++) {
            arr[k] = arrIn[k];
        }
    }
    void operator=(ArrayWrapper<i,T> & arrIn) {
        copyArr(arr, arrIn);
    }
    template < const size_t j, typename T >
    operator ArrayWrapper<j,T>() {
        ArrayWrapper<j,T> result;
        if (j < i) { 
            std::cout <<
            "Could not copy ArrayWrapper<" << i << ",T" << ">" 
                  << " into ArrayWrapper<" << j << ",T" << ">"
            << std::endl;
            return result;
        }
        copyArr(result.arr, arr);
        return result;
    }
    void print() {
        for (int j = 0; j < i; j++) {
            std::cout << arr[j] << ", ";
        }
        std::cout << std::endl;
    }
};
int main()
{
    ArrayWrapper<3, int> arr1({ 1, 2, 3 });
    ArrayWrapper<4, int> arr2 = arr1;
    arr1.print();
    arr2.print();
    ArrayWrapper<4, int> arr3({ 1, 2, 3 });
    ArrayWrapper<3, int> arr4 = arr3;
    arr3.print();
    arr4.print();
    system("PAUSE");
    return 0;
}

答案 2 :(得分:0)

这是答案:

template <const size_t i,typename T>
class ArrayWrapper {
    T arr [i] = {0};
public:
    //constructors and operators like [] ...
    template <std::size_t j, typename = std::enable_if_t<j <= i>>
    void operator=(ArrayWrapper<i,T> & arrIn){
            for (size_t k =0; k< i;k++){
                arr[k] = arrIn[k];
            }
        }
};

THX到@HolyBlackCat!