小编Hed*_*ede的帖子

为什么std :: stack不使用模板模板参数?

为什么std::stackstd::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)

c++ templates

36
推荐指数
4
解决办法
2094
查看次数

C++:std :: tuple_size/tuple_element可以专门吗?

是自定义类型的专业化std::tuple_sizestd::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)

c++ c++17

13
推荐指数
1
解决办法
850
查看次数

函数模板中的参数包后面是否可以跟另一个取决于返回类型的参数?

我有一个函数,其中模板类型参数跟随参数包。它看起来像这样:

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)

c++ visual-c++ variadic-templates

6
推荐指数
1
解决办法
431
查看次数

声明在未命名命名空间中向前声明的友元是否违反 ODR?

我一直在使用一个肮脏的技巧,我使用未命名的名称空间来为每个文件指定不同的行为(用于单元测试)。感觉它不应该被明确定义,但它适用于过去六年发布的每个主要编译器。

我首先在匿名名称空间中前向声明一堆类:

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)

c++ undefined-behavior language-lawyer unnamed-namespace

6
推荐指数
1
解决办法
145
查看次数