Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为每个模板(int)参数向类添加方法_C++_C++11_Variadic Templates - Fatal编程技术网

C++ 为每个模板(int)参数向类添加方法

C++ 为每个模板(int)参数向类添加方法,c++,c++11,variadic-templates,C++,C++11,Variadic Templates,我有一个不应该连续的数字序列。假设5,2,3,我希望它们映射到数组索引(5->0,2->1,3->2)。这是我的代码,对我来说似乎是正确的 template<size_t Index, int ...Values> struct indexer; template<size_t Index> struct indexer<Index> { }; template<size_t Index, int T, int ...Rest> struc

我有一个不应该连续的数字序列。假设5,2,3,我希望它们映射到数组索引(5->0,2->1,3->2)。这是我的代码,对我来说似乎是正确的

template<size_t Index, int ...Values> 
struct indexer;

template<size_t Index> 
struct indexer<Index> { };

template<size_t Index, int T, int ...Rest>
struct indexer<Index, T, Rest...> :
    public indexer<Index + 1, Rest...>
{
    template<int Value> size_t get();
    template<> size_t get<T>() { return Index; }
};

// this class (should) maps Values... to 0,1,2...
template<int ...Values>
struct mapper :
    public indexer<0, Values...>
{ };
模板
结构索引器;
模板
结构索引器{};
模板
结构索引器:
公共索引器
{
模板大小_t get();
模板大小\u t get(){return Index;}
};
//此类(应)映射值。。。到0,1,2。。。
模板
结构映射器:
公共索引器
{ };
现在我可以打电话:

mapper<5, 2, 3> m;
m.get<5>();   // returns 0 as expected
m.get<2>();   // does not compile
mapperm;
m、 get();//按预期返回0
m、 get();//不编译
错误1错误LNK2019:未解析的外部符号“public:unsigned int\u thiscall indexer::get(void)”(??$get@$01@?$indexer@$0A@$04$01$02@@QAEIXZ)在函数\u main C:…\ATL.Console\main.obj ATL.Console中引用


有人能解释一下怎么回事吗?m似乎没有函数get(),但为什么?

C++11不允许在类范围内显式专门化。本声明:

template<int Value> size_t get(); // primary template
template<> size_t get<T>() { return Index; }  // <-- this one
这样说(如果合法):如果重载解析选择了前一行声明的主模板
get
,并且如果传递给该成员函数模板的模板参数等同于类模板的模板参数
T
,那么下面是您应该使用的函数的定义(而不是主成员函数模板的定义)

函数模板的显式专门化为函数模板提供了另一种定义。它本身不是函数(模板),也不参与重载解析

当然,如果重载解析选择此成员函数模板,但模板参数条件不成立(=when
value!=T
),则使用主模板的定义。但主模板没有定义!因此出现链接器错误


以下是您如何做到这一点:

#include <cstddef> // for std::size_t
#include <type_traits> // for std::integral_constant

template<size_t Index, int ...Values> 
struct indexer;

template<size_t Index> 
struct indexer<Index>
{
    // provide a dummy to allow simple overloading via a using-declaration
    // if you see a linker error here, then Value could not be found
    template<int Value>
    size_t get(std::integral_constant<int, Value>);
    // it would be nice to provide a definition for the template above,
    // containing a `static_assert` for a nice compile-time error message,
    // but I'm not sure on what to assert.
};

template<size_t Index, int T, int ...Rest>
struct indexer<Index, T, Rest...> :
    public indexer<Index + 1, Rest...>
{
    template<int Value>
    size_t get()
    {
        return get(std::integral_constant<int, Value>());
    }

    // a using-declaration to allow overloading
    using indexer<Index + 1, Rest...>::get;

    size_t get(std::integral_constant<int, T>)
    { return Index; }
};

// this class (should) maps Values... to 0,1,2...
template<int ...Values>
struct mapper :
    public indexer<0, Values...>
{};
#包括//标准::尺寸#
#包含//用于标准::整定常数
模板
结构索引器;
模板
结构索引器
{
//提供一个虚拟对象,以允许通过using声明进行简单重载
//若在此处看到链接器错误,则无法找到值
模板
尺寸(标准:积分常数);
//最好为上面的模板提供一个定义,
//包含一个'static_assert',用于一个好的编译时错误消息,
//但我不确定该断言什么。
};
模板
结构索引器:
公共索引器
{
模板
大小(无法获取)
{
返回get(std::integral_constant());
}
//允许重载的使用声明
使用索引器::get;
尺寸(标准::积分常数)
{返回索引;}
};
//此类(应)将值…映射到0,1,2。。。
模板
结构映射器:
公共索引器
{};

当然,现在有许多冗余的
get(void)
成员函数模板(所有这些成员函数都可以是
static
,顺便说一句)。因此,您可以将其移动到
mapper
,甚至提供一个非成员函数。

非常感谢@dyp。只有一个细节:我的编译器需要在使用中添加typename(使用typename indexer::get)。否则,我看到内部错误occurred@vajanko内部编译器错误总是编译器中的一个错误(应该向供应商/生产者/维护者报告)。在标准C++中,<代码>类型名称< /COD>甚至是非法的,因为<代码>索引器::GET < /C> >不是类型的名称(参见).但是……如果有帮助的话;)(请注意这是一个不可移植的解决方法)
template<> size_t get<T>() { return Index; }
#include <cstddef> // for std::size_t
#include <type_traits> // for std::integral_constant

template<size_t Index, int ...Values> 
struct indexer;

template<size_t Index> 
struct indexer<Index>
{
    // provide a dummy to allow simple overloading via a using-declaration
    // if you see a linker error here, then Value could not be found
    template<int Value>
    size_t get(std::integral_constant<int, Value>);
    // it would be nice to provide a definition for the template above,
    // containing a `static_assert` for a nice compile-time error message,
    // but I'm not sure on what to assert.
};

template<size_t Index, int T, int ...Rest>
struct indexer<Index, T, Rest...> :
    public indexer<Index + 1, Rest...>
{
    template<int Value>
    size_t get()
    {
        return get(std::integral_constant<int, Value>());
    }

    // a using-declaration to allow overloading
    using indexer<Index + 1, Rest...>::get;

    size_t get(std::integral_constant<int, T>)
    { return Index; }
};

// this class (should) maps Values... to 0,1,2...
template<int ...Values>
struct mapper :
    public indexer<0, Values...>
{};