Cha*_*eon 3 c++ inheritance traits sfinae c++11
我创建了一个container_traits类来检查容器是否std::array存在.但它无法捕获从中继承的容器std::array.有解决方案吗
#include <vector>
#include <array>
#include <iostream>
using namespace std;
template<typename C>
struct container_traits { constexpr static bool is_array = false; };
template<typename T, size_t S>
struct container_traits<std::array<T,S>> { constexpr static bool is_array = true; };
template<typename T, size_t S>
struct A : public std::array<T,S> {};
int main()
{
cout << container_traits<A<int, 5>>::is_array << endl; // must return 1
cout << container_traits<std::array<int, 10>>::is_array << endl; // must return 1
cout << container_traits<std::vector<int>>::is_array << endl; // must return 0
return 0;
}
Run Code Online (Sandbox Code Playgroud)
你可以使用std::is_base_of:
template <typename C>
struct container_traits {
constexpr static bool is_array = false;
};
template <template <typename, std::size_t> class C,
typename T, std::size_t N>
struct container_traits<C<T,N>> {
constexpr static bool is_array = std::is_base_of<std::array<T,N>, C<T,N>>::value;
};
Run Code Online (Sandbox Code Playgroud)
它基本上适用于任何带有两个参数的模板类型.在这种专业化中,价值is_array取决于std::is_base_of.
作者注:请不要投票支持这个解决方案.投票支持sftrabbit,因为它比我的好.我不会删除,因为虽然存在缺陷,但有些人发现这个想法很有趣.
这给出了您想要的结果:
template<typename C>
struct container_traits {
private:
template <typename T, size_t N>
static char (&is_array_helper(const std::array<T, N>&))[1];
static char (&is_array_helper(...))[2];
public:
constexpr static bool is_array =
sizeof(is_array_helper(std::declval<C>())) == sizeof(char[1]);
};
Run Code Online (Sandbox Code Playgroud)
注意:
值得一提的是,对于派生自std::array<T, N>(例如A)继承的类,public否则代码不能编译.要解决这个问题,可以使用std::is_base_of或应用一些SFINAE技术.但是,关于可访问性的SFINAE规则已经从C++ 03改为C++ 11,而且当我刚刚测试时,一些主要编译器没有实现新规则.也许他们现在就做.
我建议问题的作者等待看看是否有更好的解决方案(我希望这会发生).