gpt4 book ai didi

c++ - 具有可变模板模板参数的方法的部分特化

转载 作者:行者123 更新时间:2023-11-30 05:12:06 24 4
gpt4 key购买 nike

我有一个代码,编译成功(g++ 4.9.2):

#include <iostream>
#include <utility>

// general function for any variadic templated argument
template<template<typename ...> class T, typename ...TTs>
void
foo(T<TTs...>& arg)
{
std::cout << "T<TTs...>" << std::endl;
}

template<typename ...Ts>
struct xxx
{
// not important
};

// specialization for only variadic templated xxx
template<typename ...TTs> void
foo(xxx<TTs...>& arg)
{
std::cout << "xxx<TTs...>" << std::endl;
}

// specialization for non-variadic templated xxx
template<typename TT> void
foo(xxx<TT>& arg)
{
std::cout << "xxx<TT>" << std::endl;
}

// specialization for xxx<uint8_t>
template<> void
foo(xxx<uint8_t>& arg)
{
std::cout << "xxx<uint8_t>" << std::endl;
}

int
main(int argc, char** argv)
{
xxx<uint8_t> x1;
std::cout << "xxx<uint8_t> => ";
foo(x1);

xxx<uint16_t> x2;
std::cout << "xxx<uint16_t> => ";
foo(x2);

xxx<uint8_t,uint16_t> x3;
std::cout << "xxx<uint8_t,uint16_t> => ";
foo(x3);

std::pair<uint8_t,uint16_t> x4;
std::cout << "std::pair<uint8_t,uint16_t> => ";
foo(x4);

return 0;
}

并产生:

xxx<uint8_t> => xxx<uint8_t>
xxx<uint16_t> => xxx<TT>
xxx<uint8_t,uint16_t> => xxx<TTs...>
std::pair<uint8_t,uint16_t> => T<TTs...>

现在我想把这些 foo 方法放在一个类中,然后写:

#include <iostream>
#include <utility>

class abc
{
public:
// general function for any variadic templated argument
template<template<typename ...> class T, typename ...TTs>
void
foo(T<TTs...>& arg)
{
std::cout << "T<TTs...>" << std::endl;
}
};

template<typename ...Ts>
struct xxx
{
// not important
};

// specialization for only variadic templated xxx
template<typename ...TTs> void
abc::foo(xxx<TTs...>& arg)
{
std::cout << "xxx<TTs...>" << std::endl;
}

// specialization for non-variadic templated xxx
template<typename TT> void
abc::foo(xxx<TT>& arg)
{
std::cout << "xxx<TT>" << std::endl;
}

// specialization for xxx<uint8_t>
template<> void
abc::foo(xxx<uint8_t>& arg)
{
std::cout << "xxx<uint8_t>" << std::endl;
}

int
main(int argc, char** argv)
{
abc p;

xxx<uint8_t> x1;
std::cout << "xxx<uint8_t> => ";
p.foo(x1);

xxx<uint16_t> x2;
std::cout << "xxx<uint16_t> => ";
p.foo(x2);

xxx<uint8_t,uint16_t> x3;
std::cout << "xxx<uint8_t,uint16_t> => ";
p.foo(x3);

std::pair<uint8_t,uint16_t> x4;
std::cout << "std::pair<uint8_t,uint16_t> => ";
p.foo(x4);

return 0;
}

这会产生一个编译错误:

test_ko.cc:24:1: error: prototype for ‘void abc::foo(xxx<TTs ...>&)’ does not match any in class ‘abc’
abc::foo(xxx<TTs...>& arg)
^
test_ko.cc:10:5: error: candidate is: template<template<class ...> class T, class ... TTs> void abc::foo(T<TTs ...>&)
foo(T<TTs...>& arg)
^
test_ko.cc:31:1: error: prototype for ‘void abc::foo(xxx<TT>&)’ does not match any in class ‘abc’
abc::foo(xxx<TT>& arg)
^
test_ko.cc:10:5: error: candidate is: template<template<class ...> class T, class ... TTs> void abc::foo(T<TTs ...>&)
foo(T<TTs...>& arg)

我想要 foo 方法的特化,而不是在 abc 类中声明新的签名(因为有一个带有模板的类、库的一部分和单独的特化,用于稍后声明的 xxx 类)。

在我看来,带有方法的代码与带有函数的代码相似,但我在这里出错了。我做错了什么?

最佳答案

// general function for any variadic templated argument
template<template<typename ...> class T, typename ...TTs>
void
foo(T<TTs...>& arg)
{
std::cout << "T<TTs...>" << std::endl;
}

这是一个模板函数。

template<typename ...Ts>
struct xxx
{
// not important
};

// specialization for only variadic templated xxx
template<typename ...TTs> void
foo(xxx<TTs...>& arg)
{
std::cout << "xxx<TTs...>" << std::endl;
}

不是特化。这是一个不同的模板函数,其名称为 foo使用上述模板函数重载。

// specialization for non-variadic templated xxx
template<typename TT> void
foo(xxx<TT>& arg)
{
std::cout << "xxx<TT>" << std::endl;
}

不是特化。这是一个不同的模板函数,其名称为 foo使用上述模板函数重载。

// specialization for xxx<uint8_t>
template<> void
foo(xxx<uint8_t>& arg)
{
std::cout << "xxx<uint8_t>" << std::endl;
}

这是上述模板函数之一的完全特化。我认为是第三个,但我不会赌钱。 (我相信如果您调用 xxx<uint8_t>& ,它会专门指定 foo 将被分派(dispatch)到的模板)。

我不会这样写:

inline foo(xxx<uint8_t>& arg)
{
std::cout << "xxx<uint8_t>" << std::endl;
}

这是 foo 的全新重载再次。重载远没有全功能特化那么古怪。

不存在部分模板函数特化这样的东西

这解释了为什么您尝试使用相同语法专门化方法不起作用。 也不存在部分模板成员函数特化这样的东西

您要么必须在类本身中编写重载,要么分派(dispatch)到不同的上下文。

“出错”的原因是您的初始代码引入了新的重载。您不得在类定义之外引入新的方法重载,因此编译器指出了您的错误。


这是一个有用的技巧。我们在abc :

// general function for any variadic templated argument
template<template<typename ...> class T, typename ...TTs>
void foo(T<TTs...>& arg)
{
return foo(*this, arg);
}
private:
template<template<typename ...> class T, typename ...TTs>
friend void foo(abc& self, T<TTs...>& arg)
{
std::cout << "T<TTs...>" << std::endl;
}

我们的 foo方法扩展到 foo friend 。

然后我们将代码添加到与 abc 相同的命名空间中:

template<typename ...TTs> void
foo(abc& self, xxx<TTs...>& arg)
{
std::cout << "xxx<TTs...>" << std::endl;
}

template<typename TT> void
foo(abc& self, xxx<TT>& arg)
{
std::cout << "xxx<TT>" << std::endl;
}

inline void foo(abc& self, xxx<uint8_t>& arg)
{
std::cout << "xxx<uint8_t>" << std::endl;
}

并且在 abc::foo 时通过 ADL 找到它们被称为。

关于c++ - 具有可变模板模板参数的方法的部分特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44709985/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com