简体   繁体   中英

variadic template function casts array type to pointer

This code has a partial user specializations for pointers and arrays.

When the array specialization is explicitly called, the expected value is returned.

However, when a variadic template function is used, the array parameter is converted to a pointer, and the pointer specialization is called.

Is there a way to get the compiler (g++ 4.8.1 in this case) to not do that cast?

Or is there a different way to return the "total size" that doesn't use template specializations?

#include <iostream>

template <typename T, typename...  Params>
struct TestTemplate
{
    static size_t Sizeof()
    {
        std::cout << __FILE__ << ':' << __LINE__ << std::endl;
        return sizeof (T) + TestTemplate<Params...>::Sizeof();
    }
};


template <typename T>
struct TestTemplate<T>
{
    static size_t Sizeof()
    {
        std::cout << __FILE__ << ':' << __LINE__ << std::endl;
        return sizeof (T);
    }
};


template <typename T, typename...  Params>
struct TestTemplate<T*, Params...>
{
    static size_t Sizeof()
    {
        std::cout << __FILE__ << ':' << __LINE__ << std::endl;
        return sizeof (T) + TestTemplate<Params...>::Sizeof();
    }
};


template <typename T>
struct TestTemplate<T*>
{
    static size_t Sizeof()
    {
        std::cout << __FILE__ << ':' << __LINE__ << std::endl;
        return sizeof (T);
    }
};


template <typename T, size_t N, typename...  Params>
struct TestTemplate<T[N], Params...>
{
    static size_t Sizeof()
    {
        std::cout << __FILE__ << ':' << __LINE__ << std::endl;
        return N * sizeof (T) + TestTemplate<Params...>::Sizeof();
    }
};


template <typename T, size_t N>
struct TestTemplate<T[N]>
{
    static size_t Sizeof()
    {
        std::cout << __FILE__ << ':' << __LINE__ << std::endl;
        return N * sizeof (T);
    }
};


template <typename... Params>
size_t GetSizeof (Params... params)
{
    return TestTemplate<Params...>::Sizeof();
}


struct TestType
{
    double x = 0., y = 0.;
    char buf[64];
};

int main (int, char *[])
{
    std::cout << TestTemplate<int[10]>::Sizeof() << std::endl; // prints 40. OK
    std::cout << GetSizeof (2, 3, 4) << std::endl; // prints 12. OK

    TestType tt;
    std::cout << GetSizeof (&tt, 1) << std::endl; // prints 84. OK

    int int_arr[10];
    std::cout << GetSizeof (int_arr, 1) << std::endl; // prints 8, want 41
}

You may replace your GetSizeof by: ( https://ideone.com/jqXT4s )

template <typename... Params>
size_t GetSizeof (const Params&... params)
{
    return TestTemplate<Params...>::Sizeof();
}

Once you have done that, you may simply use:

template <typename T, typename...  Params>
struct TestTemplate
{
    static size_t Sizeof()
    {
        std::cout << __FILE__ << ':' << __LINE__ << std::endl;
        return sizeof (typename std::remove_pointer<T>::type) + TestTemplate<Params...>::Sizeof();
    }
};

template <typename T>
struct TestTemplate<T>
{
    static size_t Sizeof()
    {
        std::cout << __FILE__ << ':' << __LINE__ << std::endl;
        return sizeof (typename std::remove_pointer<T>::type);
    }
};

as sizeof(T[N]) == N * sizeof(T) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM