3

我有点卡住了,需要 C++ 模板大师的帮助。有一个模板结构:

template<typename T, typename ID>
struct TypeMapping
{
    T Type;
    char* Name;
    ID Id;
};

和一些像这样的模板函数:

template<typename T, typename ID>
bool TryGetTypeByNameImp(const TypeMapping<T, ID> map[], size_t mapSize,
    const char* name, T& type)
{
    for (size_t i = 0; i < mapSize; i++)
    {
        if (strcmp(map[i].Name, name) == 0)
        {
            type = map[i].Type;
            return true;
        }
    }

    return false;
}

map(第一个参数)定义为(有几个类似的map)

namespace audio
{ 
    const TypeMapping<Type, AMF_CODEC_ID> Map[] = 
    {
        {AAC, "aac", AMF_CODEC_AAC},
        {MP3, "mp3", AMF_CODEC_MP3},
        {PCM, "pcm", AMF_CODEC_PCM_MULAW}
    };

    const size_t MapSize =  sizeof(Map)/sizeof(Map[0]);
}

Map 作为参数传递给函数,我正在寻找如何将其作为模板参数传递,以便可以使用此示例中的函数:

 audio::Type type;
 bool r = TryGetTypeByNameImp<audio::Map>("aac", type);

我发现的唯一解决方案是定义一个包含静态 Map 和 MapSize 的结构并将该结构用作模板参数,但我不喜欢这个解决方案,我正在寻找另一个解决方案。有人知道怎么做这个吗?

4

2 回答 2

2
bool r = TryGetTypeByNameImp<audio::Map>("aac", type);

这是试图audio::Map用作一种类型——但它不是,它是一个变量。只需将其作为普通参数传递给函数:

bool r = TryGetTypeByNameImp(audio::Map, "aac", type);

也就是说,我对您的代码有三点评论:

  • 请注意,将函数参数声明为数组 ( x[]) 实际上确实将其声明为指针。您的代码正确使用了它,但使用数组语法会产生误导。请改用指针。
  • 这段代码对我的口味来说有点太重了。虽然我同意在这里使用原始 C 字符串是合适的,但您char*在 C++11 中的使用是非法的,并且在 C++03 中已弃用(因为您指向的是字符串文字)。使用char const*. 此外,我建议std::string在函数中使用参数,并使用比较运算符==而不是strcmp.
  • 您正在使用外参数,type. 我讨厌这种技术。如果要返回值,请使用返回类型。由于您还返回一个成功值,请使用 apair作为返回类型,除非有非常令人信服的理由不这样做:

    template<typename T, typename ID>
    std::pair<bool, T> TryGetTypeByNameImp(
        const TypeMapping<T, ID> map[], size_t mapSize,
        const char* name)
    {
        for (size_t i = 0; i < mapSize; i++)
            if (strcmp(map[i].Name, name) == 0)
                return std::make_pair(true, map[i].Type);
    
        return std::make_pair(false, T());
    }
    

Ah, and I’d also consider using a std::vector or std::array here instead of a C array. Then you don’t need to manually shlep the array size around through all the functions which use the array.

于 2012-08-03T10:10:46.143 回答
1

您当然可以使用数组本身(嗯,指向它的指针)作为模板参数:

#include <iostream>
template<typename T> struct S { T t; };
S<int> s[] = { { 21 }, { 22 } };
template<typename T, size_t n, S<T> (*m)[n]> void f() { std::cout << (*m)[n - 1].t; }
int main() {
    f<int, 2, &s>();
}

这里的问题是您不能对数组的长度或其类型使用模板参数推导,因此除了数组本身之外,两者都必须作为模板参数提供。我真的认为传递一个结构,或者说一个向量会是更好的解决方案,因为你无疑已经探索过:

#include <vector>
#include <iostream>
template<typename T> struct S { T t; };
std::vector<S<int>> s{ { 21 }, { 22 } };
template<typename T, std::vector<S<T>> *v> void f() { std::cout << v->back().t; }
int main() {
    f<int, &s>();
}
于 2012-08-03T10:04:46.407 回答