我在尝试编译时遇到了这样的问题:
#include <vector>
#include <array>
struct Test
{
template <template <typename...> class Container, typename T, typename... Args>
void SetData(const Container<T, Args...>& data)
{
// compiles for vector but not array
// 'void Test::SetData(const Container<T,Args...> &)': could not deduce template argument for 'const Container<T,Args...> &' from 'std::array<float,3>'
}
};
int main()
{
Test test;
std::vector<int> vector{ 1,2,3 };
std::array<float, 3> arr{1.0f, 2.0f, 3.0f};
test.SetData(vector);
test.SetData(arr);
return 0;
}
本质上,我需要一个可以接受任意 STL 容器(更具体地说是 std::vector
和 std::array
)的函数签名,并且我需要类型 T
在函数中也可见(即本例中的 int
或 float
)。其他类型(分配器或 std::array
大小)我不关心。
什么是正确的签名?
最佳答案
What is the correct signature?
据我所知,不可能编写一个正确的签名来拦截所有容器并且只拦截容器。
但是如果你接受编写一个类型特征来说明一个类型是否是一个容器并提取包含的类型(需要一个通用版本,一个 std::vector
和类似的 typename ...
容器的部分特化和一个 std::array
的特化;其他特化可以是添加)如下 isCnt
template <typename>
struct isCnt : public std::false_type
{ };
// std::array case
template <template <typename, std::size_t> class C,
typename T, std::size_t N >
struct isCnt<C<T, N>> : public std::true_type
{ using containedType = T; };
// other container case
template <template <typename ...> class C,
typename T0, typename ... Ts>
struct isCnt<C<T0, Ts...>> : public std::true_type
{ using containedType = T0; };
你可以如下构造setData()
模板::containedType> void SetData(C 常量和数据) { //代码在这里
观察 setData()
是否由 T = isCnt<C>::containedType
启用(或禁用)SFINAE,这仅适用于容器。
下面是一个完整的工作示例
#include <array>
#include <vector>
#include <iostream>
#include <type_traits>
template <typename>
struct isCnt : public std::false_type
{ };
// std::array case
template <template <typename, std::size_t> class C,
typename T, std::size_t N >
struct isCnt<C<T, N>> : public std::true_type
{ using containedType = T; };
// other container case
template <template <typename ...> class C,
typename T0, typename ... Ts>
struct isCnt<C<T0, Ts...>> : public std::true_type
{ using containedType = T0; };
struct Test
{
template <typename C, typename T = typename isCnt<C>::containedType>
void SetData (C const & data)
{
if ( std::is_same<T, int>::value )
std::cout << "- int case" << std::endl;
else if ( std::is_same<T, float>::value )
std::cout << "- float case" << std::endl;
}
};
int main ()
{
Test test;
std::vector<int> vector{ 1,2,3 };
std::array<float, 3> arr{ { 1.0f, 2.0f, 3.0f } };
test.SetData(vector); // print "int case"
test.SetData(arr); // print "float case"
//test.SetData(0); // compilation error
}
关于c++ - 正确获取模板化模板函数声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46125870/