第二参数的部分模板专业化

时间:2018-06-21 20:29:26

标签: c++ c++11 templates specialization

我正在围绕C api开发C ++ 11包装器。 C api提供了一堆用于各种类型的getter,每种类型都有不同的名称。通过编译时已知的给定大小的数组来检索值。

我想通过模板给出类型和数组大小,以调用正确的函数。

#include <string>
#include <iostream>

template <typename T>
struct make_stop {
    constexpr static bool value = false;
};

class Foo
{
public:
    Foo() : i(42) {}

    template<typename T, size_t n>
    T get();

private:
    int i = 0;
};

template<typename T, size_t n>
T Foo::get() { static_assert(make_stop<T>::value); return T(); }

template<int, size_t n>
int Foo::get() { return i + n; }

int main() {
    Foo foo;

    int i = foo.get<int, 4>();
    double f = foo.get<double, 2>();


    return 0;
}

但是它无法匹配正确的功能

main.cpp:26:5: error: no declaration matches 'int Foo::get()'

 int Foo::get() { return i + n; }
     ^~~

main.cpp:15:7: note: candidate is: 'template<class T, long unsigned int n> T Foo::get()'

     T get();

2 个答案:

答案 0 :(得分:1)

它对您的问题有点迷惑,但是假设您要索引某些c数组并返回I处的值,则无法像您想要的那样专门化函数模板,但是可以使用一些标签相反,类似..

class Foo
{
public:
    Foo() : is{1,2,3,4,5,6,7,8,9,10},ds{1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9,10.1} {}


    template <typename T> struct type_c{};
    template <size_t I> struct int_c{};

    template<typename T,size_t I>
    auto get() 
    { return get_impl(type_c<T>(),int_c<I>()); }

private:

    template <size_t I>
    auto get_impl(type_c<int>,int_c<I>) 
    { return is[I]; }

    template <size_t I>
    auto get_impl(type_c<double>,int_c<I>) 
    { return ds[I]; }


    int is[10];
    double ds[10];
};
int main() {
    Foo foo;

    int i = foo.get<int,0>();
    double d = foo.get<double,2>();
    std::cout << i << " " << d << std::endl;
    return 0;
}

Demo

答案 1 :(得分:0)

如果我对您的理解正确,那么您想partially专门从事T的培训。不幸的是,标准不允许方法的部分专业化。不过,您可以在T模板化的类上使用静态方法来解决此问题,并对该类进行专门化处理。

赞:

template <class T> struct Foo_helper;

struct Foo
{
    Foo() : i{42} {}

    template<class T, std::size_t N>
    T get()
    {
        return Foo_helper<T>::template get<N>(*this);
    }

    int i = 0;
};

template <class T> struct Foo_helper {};
// specialize Foo_helper for each type T you wish to support:

template <> struct Foo_helper<int>
{
    template <std::size_t N>
    static int get(const Foo& foo) { return foo.i + N; }
};
template <> struct Foo_helper<double>
{
    template <std::size_t N>
    static double get(const Foo& foo) { return foo.i + N; }
};


int main()
{
    Foo foo{};

    int i = foo.get<int, 4>();
    double d = foo.get<double, 2>();
}