C++ 如何使用 vector<T> 专门化模板?
C++ How to specialize a template using vector<T>?
基本上,我想让函数对矢量(类型)参数和非矢量类型参数表现不同。
#include <vector>
using namespace std;
template <typename type>
struct is_vector {
static const bool value = false;
};
template <typename type>
struct is_vector<vector<type>>
{
static const bool value = true;
};
template <typename type>
type read()
{
if (is_vector<type>::value)
{
type vec(10);
vec.front()=1;//left of '.front' must have class/struct/union
return vec;
}
else
{
return{};
}
}
int main()
{
auto i= read<int>();
}
我想 return 一个向量,同时使用 vector 作为类型名,return 一个 int,同时使用 int 作为类型名。
但是因为 is_vector(int)::value returns false,为什么我的编译器会报告 "left of '.front' must have class/struct/union"?我怎样才能让它工作?
我想要实现的是将字符串正确反序列化为 vector(type) 或 vector(vector(type)) 。
我需要递归调用读取函数,同时将多维向量作为模板参数传递,但编译器禁止我这样做。
template <typename type>
struct is_vector {
static const bool value = false;
};
template <typename type>
struct is_vector<vector<type>>
{
static const bool value = true;
};
template <typename type>
type read(char*& str)
{
if (is_vector<type>::value)
{
type vec(read<uint8_t>(str));
for (auto& e : vec)
e = read<type::value_type>(str);
return vec;
}
return *reinterpret_cast<type*>((str += sizeof(type)) - sizeof(type));
}
所以我尝试了专业化。
template<>
vector<int> read<vector<int>>(char*& str)
{
vector<int> vec(read<uint8_t>(str));
for (auto& e : vec)
e = read<int>(str);
return vec;
}//works
template <typename type>
template <>
vector<type> read<vector<type>>(char*& str)
{
vector<type> vec(read<uint8_t>(str));
for (auto& e : vec)
e = read<type>(str);
return vec;
}//don't work
我真的需要为我使用的每种类型手动重写我的读取函数吗?
(像向量(向量(向量(int)))?)
您需要一个至少参数化的函数模板 foo<R>
通过 return 输入 R
,并且您想要一个专门的实现
当 R
= std::vector<U>
时,对于任意类型 U
.
foo<R>
的参数是什么并不重要,所以为了说明
我们假设没有。方法如下:
定义一个特征模板如下:
template<typename T>
struct is_vector
{
static constexpr bool value = false;
};
template<template<typename...> class C, typename U>
struct is_vector<C<U>>
{
static constexpr bool value =
std::is_same<C<U>,std::vector<U>>::value;
};
有了这个,
is_vector<T>::value
当且仅当 T
= std::vector<U>
时 在编译时为真,对于某些 U
.
然后在以下行中定义 foo<R>()
的两个重载:
template <typename R>
std::enable_if_t<!is_vector<R>::value,R> foo()
{
// Your non-vector implementation instead of...
std::cout <<
"In non-vector specialization of `foo<R>()`\n";
return R();
}
template <typename R>
std::enable_if_t<is_vector<R>::value,R> foo()
{
// Your vector implementation instead of...
std::cout <<
"In vector specialization of `foo<R>()`\n";
return R();
}
这两个重载是互斥的,并且是共同穷尽的。这
当且仅当 is_vector<R>::value
为假时,第一个重载才成为合法代码。这
当且仅当 is_vector<R>::value
为真时,第二个重载才成为合法代码。
这要归功于 std::enable_if
的行为,
你应该学习和理解。
当编译器需要选择这些模板重载之一来实现一些
调用它在您的代码中找到的 foo<type>()
,它发现正是其中一个重载
当为模板参数 R
插入 type
时甚至不会编译。如果第一个不会编译
type
是一些 std::vector<U>
如果 type
是 不是 则第二个将无法编译
std::vector<U>
。有用的是,编译器选择了它可以编译的那个。
那叫SFINAE
("Substitution Failure Is Not An Error"),
它是您问题的解决方案。
这是一个说明性程序:
#include <vector>
#include <type_traits>
#include <iostream>
template<typename T>
struct is_vector
{
static constexpr bool value = false;
};
template<template<typename...> class C, typename U>
struct is_vector<C<U>>
{
static constexpr bool value =
std::is_same<C<U>,std::vector<U>>::value;
};
template <typename R>
std::enable_if_t<!is_vector<R>::value,R> foo()
{
// Your non-vector implementation instead of...
std::cout <<
"In non-vector specialization of `foo<R>()`\n";
return R();
}
template <typename R>
std::enable_if_t<is_vector<R>::value,R> foo()
{
// Your vector implementation instead of...
std::cout <<
"In vector specialization of `foo<R>()`\n";
return R();
}
int main()
{
auto i = foo<int>();
(void)i;
auto vc = foo<std::vector<char>>();
(void)vc;
return 0;
}
这将输出:
In non-vector specialization of `foo<R>()`
In vector specialization of `foo<R>()`
(gcc 6.1/clang 3.8, -std=c++14
see live)
基本上,我想让函数对矢量(类型)参数和非矢量类型参数表现不同。
#include <vector>
using namespace std;
template <typename type>
struct is_vector {
static const bool value = false;
};
template <typename type>
struct is_vector<vector<type>>
{
static const bool value = true;
};
template <typename type>
type read()
{
if (is_vector<type>::value)
{
type vec(10);
vec.front()=1;//left of '.front' must have class/struct/union
return vec;
}
else
{
return{};
}
}
int main()
{
auto i= read<int>();
}
我想 return 一个向量,同时使用 vector 作为类型名,return 一个 int,同时使用 int 作为类型名。
但是因为 is_vector(int)::value returns false,为什么我的编译器会报告 "left of '.front' must have class/struct/union"?我怎样才能让它工作?
我想要实现的是将字符串正确反序列化为 vector(type) 或 vector(vector(type)) 。
我需要递归调用读取函数,同时将多维向量作为模板参数传递,但编译器禁止我这样做。
template <typename type>
struct is_vector {
static const bool value = false;
};
template <typename type>
struct is_vector<vector<type>>
{
static const bool value = true;
};
template <typename type>
type read(char*& str)
{
if (is_vector<type>::value)
{
type vec(read<uint8_t>(str));
for (auto& e : vec)
e = read<type::value_type>(str);
return vec;
}
return *reinterpret_cast<type*>((str += sizeof(type)) - sizeof(type));
}
所以我尝试了专业化。
template<>
vector<int> read<vector<int>>(char*& str)
{
vector<int> vec(read<uint8_t>(str));
for (auto& e : vec)
e = read<int>(str);
return vec;
}//works
template <typename type>
template <>
vector<type> read<vector<type>>(char*& str)
{
vector<type> vec(read<uint8_t>(str));
for (auto& e : vec)
e = read<type>(str);
return vec;
}//don't work
我真的需要为我使用的每种类型手动重写我的读取函数吗?
(像向量(向量(向量(int)))?)
您需要一个至少参数化的函数模板 foo<R>
通过 return 输入 R
,并且您想要一个专门的实现
当 R
= std::vector<U>
时,对于任意类型 U
.
foo<R>
的参数是什么并不重要,所以为了说明
我们假设没有。方法如下:
定义一个特征模板如下:
template<typename T>
struct is_vector
{
static constexpr bool value = false;
};
template<template<typename...> class C, typename U>
struct is_vector<C<U>>
{
static constexpr bool value =
std::is_same<C<U>,std::vector<U>>::value;
};
有了这个,
is_vector<T>::value
当且仅当 T
= std::vector<U>
时 在编译时为真,对于某些 U
.
然后在以下行中定义 foo<R>()
的两个重载:
template <typename R>
std::enable_if_t<!is_vector<R>::value,R> foo()
{
// Your non-vector implementation instead of...
std::cout <<
"In non-vector specialization of `foo<R>()`\n";
return R();
}
template <typename R>
std::enable_if_t<is_vector<R>::value,R> foo()
{
// Your vector implementation instead of...
std::cout <<
"In vector specialization of `foo<R>()`\n";
return R();
}
这两个重载是互斥的,并且是共同穷尽的。这
当且仅当 is_vector<R>::value
为假时,第一个重载才成为合法代码。这
当且仅当 is_vector<R>::value
为真时,第二个重载才成为合法代码。
这要归功于 std::enable_if
的行为,
你应该学习和理解。
当编译器需要选择这些模板重载之一来实现一些
调用它在您的代码中找到的 foo<type>()
,它发现正是其中一个重载
当为模板参数 R
插入 type
时甚至不会编译。如果第一个不会编译
type
是一些 std::vector<U>
如果 type
是 不是 则第二个将无法编译
std::vector<U>
。有用的是,编译器选择了它可以编译的那个。
那叫SFINAE
("Substitution Failure Is Not An Error"),
它是您问题的解决方案。
这是一个说明性程序:
#include <vector>
#include <type_traits>
#include <iostream>
template<typename T>
struct is_vector
{
static constexpr bool value = false;
};
template<template<typename...> class C, typename U>
struct is_vector<C<U>>
{
static constexpr bool value =
std::is_same<C<U>,std::vector<U>>::value;
};
template <typename R>
std::enable_if_t<!is_vector<R>::value,R> foo()
{
// Your non-vector implementation instead of...
std::cout <<
"In non-vector specialization of `foo<R>()`\n";
return R();
}
template <typename R>
std::enable_if_t<is_vector<R>::value,R> foo()
{
// Your vector implementation instead of...
std::cout <<
"In vector specialization of `foo<R>()`\n";
return R();
}
int main()
{
auto i = foo<int>();
(void)i;
auto vc = foo<std::vector<char>>();
(void)vc;
return 0;
}
这将输出:
In non-vector specialization of `foo<R>()`
In vector specialization of `foo<R>()`
(gcc 6.1/clang 3.8, -std=c++14
see live)