为什么std::stack和std::queue使用类型模板参数,而不是模板的模板参数为他们的基础容器类型?
即为什么stack声明如下:
template<typename T, typename Container = deque<T>>
class stack;
Run Code Online (Sandbox Code Playgroud)
但不是这样的:
template<typename T, template<typename> class Container = deque>
class stack;
Run Code Online (Sandbox Code Playgroud)
?
是自定义类型的专业化std::tuple_size和std::tuple_element允许吗?我想是的,但我想绝对肯定,我找不到任何具体的信息.
示例(get<I>省略名称,成员函数和重载省略):
template <typename T, size_t N>
struct vector { T _data[N]; };
template<size_t I, typename T, size_t N>
constexpr T& get(vector<T,N>& vec) { return vec._data[I]; }
namespace std {
template<typename T, size_t N>
class tuple_size< vector<T,N> > : public std::integral_constant<size_t, N> { };
template<size_t I, typename T, size_t N>
class tuple_element< I, vector<T,N> > { public: using type = T; };
}
Run Code Online (Sandbox Code Playgroud)
我需要它用于结构化绑定:
void f(vector<T,3> const& vec)
{
auto& [x,y,z] = vec;
// …Run Code Online (Sandbox Code Playgroud) 我有一个函数,其中模板类型参数跟随参数包。它看起来像这样:
template<typename...Args, typename T>
T* default_factory_func()
{
return new T;
}
Run Code Online (Sandbox Code Playgroud)
Visual C++ 编译器拒绝它并显示错误C3547: template parameter 'T' cannot be used because it follows a template parameter pack and cannot be deduced from the function parameters of 'default_factory_func'。
但是,我尝试了编译器资源管理器上可用的各种版本的 GCC(从 4.4.7 开始)和 clang(从 3.1 开始),它们都可以很好地编译此类代码。
// this code is just a minimal example condensed
// from a much more complex codebase
template<typename T>
T* construct(T* (*factory_func)())
{
return factory_func();
}
template<typename...Args, typename T>
T* default_factory_func() // C3547 on this …Run Code Online (Sandbox Code Playgroud) 我一直在使用一个肮脏的技巧,我使用未命名的名称空间来为每个文件指定不同的行为(用于单元测试)。感觉它不应该被明确定义,但它适用于过去六年发布的每个主要编译器。
我首先在匿名名称空间中前向声明一堆类:
namespace {
class context_check;
class context_block;
class register_test;
} // namespace
Run Code Online (Sandbox Code Playgroud)
然后我声明一个类并创建这些类friend:
struct test_case
{
// ...
};
class context {
// ...
private:
// TODO: this feels like ODR-violation...
friend class context_check;
friend class context_block;
friend class register_test;
private:
void add_test(test_case&& test)
{
// ...
}
// ...
};
Run Code Online (Sandbox Code Playgroud)
在每个 cpp 文件中,我都有以下声明(为了简单起见,我将它们复制并粘贴到此处,但实际上我在标头中声明了未命名命名空间的内容):
// A.cpp
namespace {
extern context file_context;
class register_test {
public:
register_test(const char* test_name, test_case&& test)
{
file_context.add_test(std::move(test));
}
};
} // namespace …Run Code Online (Sandbox Code Playgroud)