我可以想象以下代码:
template <typename T> class X
{
public:
T container;
void foo()
{
if(is_vector(T))
container.push_back(Z);
else
container.insert(Z);
}
}
// somewhere else...
X<std::vector<sth>> abc;
abc.foo();
Run Code Online (Sandbox Code Playgroud)
如何编写,成功编译?我知道类型特征,但是当我定义时:
template<typename T> struct is_vector : public std::false_type {};
template<typename T, typename A>
struct is_vector<std::vector<T, A>> : public std::true_type {};
Run Code Online (Sandbox Code Playgroud)
它不编译:
error: no matching function for call to 'std::vector<sth>::insert(Z)'
Run Code Online (Sandbox Code Playgroud)
static_assert也不是我想要的.有什么建议吗?
这是我想要实现的一个简短例子(SSCCE):http://ideone.com/D3vBph
gal*_*p1n 29
它被命名为tag dispatching:
#include <vector>
#include <set>
#include <type_traits>
template<typename T> struct is_vector : public std::false_type {};
template<typename T, typename A>
struct is_vector<std::vector<T, A>> : public std::true_type {};
template <typename T>
class X {
T container;
void foo( std::true_type ) {
container.push_back(0);
}
void foo( std::false_type ) {
container.insert(0);
}
public:
void foo() {
foo( is_vector<T>{} );
}
};
// somewhere else...
int main() {
X<std::vector<int>> abc;
abc.foo();
X<std::set<int>> def;
def.foo();
}
Run Code Online (Sandbox Code Playgroud)
另一个值得考虑的方法是使用SFINAE检测push_back函数的存在.这稍微更通用,因为它将转换为实现push_back的其他容器.
template<typename T>
struct has_push_back
{
template<typename U>
static std::true_type test(
decltype((void(U::*)(const typename U::value_type&)) &U::push_back)*);
template<typename>
static std::false_type test(...);
typedef decltype(test<T>(0)) type;
static constexpr bool value =
std::is_same<type, std::true_type>::value;
};
Run Code Online (Sandbox Code Playgroud)
请注意,它目前只检测push_back(const T&)而不是push_back(T&&).检测两者有点复杂.
以下是您如何利用它来实际插入.
template<typename C, typename T>
void push_back_impl(C& cont, const T& value, std::true_type) {
cont.push_back(value);
}
template<typename C, typename T>
void push_back_impl(C& cont, const T& value, std::false_type) {
cont.insert(value);
}
template<typename C, typename T>
void push_back(C& cont, const T& value) {
push_back_impl(cont, value, has_push_back<C>::type());
}
std::vector<int> v;
push_back(v, 1);
std::set<int> s;
push_back(s, 1);
Run Code Online (Sandbox Code Playgroud)
老实说,这个解决方案比我原先预期的要复杂得多,所以除非你真的需要,否则我不会使用它.虽然它不是太难支持const T&和T&&,它更神秘的代码,你必须保持这可能是不值得的,在大多数情况下.
小智 5
仅使用插入:
#include <iostream>
#include <vector>
#include <set>
template <typename T>
class X
{
public:
T container;
template <typename U>
void insert(const U& u) {
container.insert(container.end(), u);
}
};
int main() {
X<std::vector<int>> v;
v.insert(2);
v.insert(1);
v.insert(0);
for(std::vector<int>::const_iterator pos = v.container.begin();
pos != v.container.end();
++pos)
{
std::cout << *pos;
}
std::cout << '\n';
X<std::set<int>> s;
s.insert(2);
s.insert(1);
s.insert(0);
for(std::set<int>::const_iterator pos = s.container.begin();
pos != s.container.end();
++pos)
{
std::cout << *pos;
}
std::cout << '\n';
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3842 次 |
| 最近记录: |