C++:使函数调用依赖于模板参数

4
在一个C++模板函数内,我想调用另一个未声明的重载函数。由于该函数不是依赖项,编译器将无法解析它。
代码如下:
#include <array>
#include <iostream>
#include <string>

template <typename T>
void serialize(const T &data)
{
    size_t data_size = getSize(data);
    std::cout << "Size: " << data_size << std::endl;
}

constexpr size_t getSize(const int &)
{
    return sizeof(int);
}

size_t getSize(const std::string &str)
{
    return str.size();
}

template <typename T, size_t N>
size_t getSize(const std::array<T, N> &array)
{
    size_t array_size = 0;
    for (const T &element : array)
        array_size += getSize(element);
    return array_size;
}

int main()
{
    int a;
    serialize(a);

    std::string str = "foo";
    serialize(str);

    std::array<std::string, 2> arr = {{"foo", "foobar"}};
    serialize(arr);

    return 0;
}

有没有好的方法使getSize()变得有依赖性?或者还有其他实现方式吗?


getSize()声明为模板函数,并为特定类型进行专门化。 - Slava
你如何声明模板化的 getSize() 函数用于数组? - Dino
实际上,你需要一个辅助结构体,请参考我的答案。 - Slava
2个回答

4
您可以将getSize()成员放在一个辅助结构体中:
template <typename T>
struct size_getter {
    static size_t getSize( T );
};

template <typename T>
void serialize(const T &data)
{
    size_t data_size = size_getter<T>::getSize( data );
    std::cout << "Size: " << data_size << std::endl;
}

然后进行专业化处理:
template<>
struct size_getter<std::string> {
    static size_t getSize( const std::string &s )
    {
        return s.size();
    }
};

template <typename T, size_t N>
struct size_getter<std::array<T, N>>
{
    static size_t getSize(const std::array<T, N> &array)
    {
        size_t array_size = 0;
        for (const T &element : array)
            array_size += size_getter<T>::getSize(element);
        return array_size;
    }
};

Live example


2
你可以添加一个虚拟标签来允许 ADL:
template <typename T> struct tag {};

template <typename T>
void serialize(const T &data)
{
    size_t data_size = getSize(data, tag<T>{});
    std::cout << "Size: " << data_size << std::endl;
}

constexpr size_t getSize(const int &, tag<int>)
{
    return sizeof(int);
}

size_t getSize(const std::string &str, tag<std::string>)
{
    return str.size();
}

template <typename T, size_t N>
size_t getSize(const std::array<T, N> &array, tag<std::array<T, N>>)
{
    size_t array_size = 0;
    for (const T &element : array)
        array_size += getSize(element, tag<T>{});
    return array_size;
}

Demo


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接