小编gla*_*des的帖子

需要模板的某些特殊化作为模板参数

我有一个数据结构meta_array,它用变体实例化为类型 T 参数。要求是 std::variant 特化必须包含类型,meta_array_head_t因为它用于跟踪信息。我可以使用类型特征(C++17)以某种方式将其声明为要求吗?

编译器资源管理器

#include <cstdio>
#include <variant>
#include <array>

struct meta_array_head_t {
    // end_;
    // remaining_;
    // prev_;
};

template <typename T, size_t S> // make sure T = std::variant<... , meta_array_head_t, ...>
struct meta_array
{
    std::array<T, S> data_; 
};


using val = std::variant<std::monostate, int, double, meta_array_head_t>;

int main()
{
    meta_array<val, 100> marray;
}
Run Code Online (Sandbox Code Playgroud)

c++ templates type-traits template-specialization c++17

2
推荐指数
1
解决办法
182
查看次数

我应该预防性地移动可调用对象(例如 lambda 吗?)

我有一个计时器的精简示例,我希望可以使用任何类型的可调用来实例化它。为了提高效率,是否建议预防性地将可调用对象移至数据成员中?

#include <concepts>
#include <cstdio>
#include <string>
#include <utility>

template <std::invocable Cb>
class timer {
public:
    timer(Cb cb)
        : cb_ { std::move(cb) }
    {
    }

    auto call()
    {
        cb_();
    }

private:
    Cb cb_;
};

int main()
{
    std::string something_to_print = "Hello World!\n";
    timer some_timer([&]() { printf(something_to_print.c_str()); });
    some_timer.call();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果移动或复制 lambda,我看不到程序集有任何差异。它有什么区别吗?

c++ lambda move-semantics

2
推荐指数
1
解决办法
58
查看次数

constexpr 真的意味着 const 吗?

比较以下内容:

我在一个类中有一个静态成员,要么是const constexpr要么只是constexpr. 根据MS Docs上的解释,constexpr 意味着常量:

所有 constexpr 变量都是 const。

然而,这会在 gcc 8.4 中发出警告:

#include <iostream>
#include <string>

struct some_struct
{
    static constexpr char* TAG = "hello";
    void member() {
        printf("printing the tag %s", TAG);
    }  
};

int main()
{
    some_struct A;
    A.member();
}
Run Code Online (Sandbox Code Playgroud)

虽然这不会:

#include <iostream>
#include <string>

struct some_struct
{
    static const constexpr char* TAG = "hello";
    void member() {
        printf("printing the tag %s", TAG);
    }  
};

int main()
{
    some_struct A; …
Run Code Online (Sandbox Code Playgroud)

c++ constants static-members constexpr c++17

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

扩展可变参数模板参数以在例如 std::variant&lt;T...&gt; 中使用

这将是一个很难解决的问题。我什至不知道这是否可能。

我的目标是创建一个接收函数,该函数侦听多个队列并将通过特定队列(首先响应)接收的对象粘贴到 return 语句中的堆栈。这将通过 std::variant 完成。棘手的部分是类型:每个队列都保存不同的类型,因此 multireceive() 内部的变体需要根据用于作为可变参数传递到其中的队列的模板参数来构造。当然,最终队列对象只能作为引用传递。

到目前为止,这是我的方法,但是您可以看到我非常不清楚如何编写包扩展。我想我可能正在突破 C++ 的极限:

#include <array>
#include <variant>

template <typename T>
struct queue
{
    T queue_[100];
    
    T receive()
    {
        return queue_[0];
    }
};

// doesn't compile!
template <template <typename... T> class Q>
std::variant<T...> multireceive(Q<T>&... Arg)
{
    std::array<std::variant<Arg*...>, sizeof...(T)> queues = { (&Arg )... };

    do {
        for (size_t i=0; i < sizeof...(T); ++i) {
            if (queues[i]->receive()) {
                return *queues[i];
            }
        }
    } while(1) // busy wait
}

int main() {}
Run Code Online (Sandbox Code Playgroud)

显然,这甚至不能远程编译,这只是我试图表明意图。队列当然也只是一个存根。据我所知,您甚至无法通过名称(T)获取模板模板参数,这是非常不幸的。有比我聪明的人已经知道如何解决这个问题了吗? …

c++ variadic-templates c++17

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

根据传递给构造函数的参数数量进行推导

这是我正在尝试的东西,但似乎不起作用:我想根据类对象的实例化方式来切换编译时开关。如果只有一个构造函数参数,则LengthOpt应该等于false,否则等于true(我的实现有多个构造函数,其中开关应默认为true.

我尝试创建一个推导指南,但显然如果模板参数没有显示为构造函数参数(这真是令人沮丧),它就不起作用。有谁知道这个问题的不太详细的解决方案?

代码

#include <cstring>
#include <iostream>

const char* str = "some input string";


template <bool LengthOpt>
class some_class
{
public:
    some_class(const char*) {
        std::cout << std::boolalpha << LengthOpt << std::endl;
    }
    some_class(const char*, size_t len) {
        std::cout << std::boolalpha << LengthOpt << std::endl;
    }
};

template <bool LengthOpt> some_class(const char*) -> some_class<false>;
template <bool LengthOpt> some_class(const char*, size_t) -> some_class<true>;

int main()
{
    some_class A(str);
    some_class B(str, strlen(str));
}
Run Code Online (Sandbox Code Playgroud)

错误 …

c++ constructor-overloading c++17 ctad deduction-guide

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

成员指针的类型未被识别为&lt;值类型&gt;

下面的代码示例尝试提取foo先前输入到函数中的结构的成员指针的值类型serialize()

这可能需要进一步解释:我想最终迭代结构体的每个成员foo,并根据每个成员指针的值类型应用某些操作。看一看:

演示

#include <cstdio>
#include <utility>
#include <tuple>
#include <typeinfo>

/* Struct with two int members */

struct foo
{
    int a_;
    int b_;
};

/* Saves member pointers */

template<auto Ptr>
struct proxy
{
    decltype(Ptr) mem_ptr_;
};

/* Conglomerate of all member ptrs of a struct */

template <typename T>
struct type_descriptor;

template <>
struct type_descriptor<foo>
{
    using type = std::tuple<proxy<&foo::a_>, proxy<&foo::b_>>;
};

/* Extract member ptr value type */

template<typename T> …
Run Code Online (Sandbox Code Playgroud)

c++ templates typeid member-pointers template-meta-programming

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

为什么 lambda 捕获中的“this”与指向同一对象的指针的处理方式不同?

如果我在 lambda 中捕获“this”-ptr,我就可以毫无问题地调用成员函数。但是,当我明确捕获指针(不提及“this”)时,它会停止工作。难道我做错了什么?根据我的理解,指针应该是一样的,所以这真的让我很惊讶。是否有一些编译器魔法以特殊的方式处理“this”?

演示

#include <cstdio>
#include <string>

struct client
{

    auto foo(std::string&& other)
    {
        printf("%s!\n", other.data());
    }

    void local()
    {
        std::string str = "Hello World this is a sentence to long for sso!";
        auto lambda = [this, other = std::move(str)]() mutable {
            foo(std::move(other));
        }();
    }

    static auto external(void* ptr) {
        std::string str = "Hello World this is a sentence to long for sso!";

        client* conv_ptr = static_cast<client*>(ptr);
        auto lambda = [conv_ptr, other = std::move(str)]() mutable {
            foo(std::move(other));
        }();
    } …
Run Code Online (Sandbox Code Playgroud)

c++ lambda closures capture this-pointer

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

根据类模板参数启用成员函数重载

这可能是一个愚蠢的问题,但我可以以某种方式使用没有模板参数的 require 子句吗?我有以下案例:

演示

#include <concepts>
#include <iostream>

template <typename T>
struct entity {
    requires (std::same_as<T, int>) 
    auto operator=(const entity&) { std::cout << "with T == int" << std::endl; return *this; }

    auto operator=(const entity&) { std::cout << "all else" << std::endl; return *this; }
};
Run Code Online (Sandbox Code Playgroud)

我想基于类模板参数而不是方法模板参数启用一个重载。我如何内联并使用概念来做到这一点?

c++ templates class-method c++20

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

如果基类是通过模板继承的,则在派生构造函数中初始化基类成员

鉴于我知道我的基类中存在某个成员a,我如何使用模板派生类来引用它?即使我完全符合资格a,它也不起作用:

演示

#include <iostream>
#include <string_view>
#include <memory>
#include <string>

struct base {
    int a;
};

template <typename ImplType>
struct derived : public ImplType {

    derived()
        : a{2}
    {}

    auto print() {
        std::cout << ImplType::a << std::endl;
    }
};

int main() {
    derived<base> d{};
    d.print();
}
Run Code Online (Sandbox Code Playgroud)

产量:

<source>:14:11: error: class 'derived<ImplType>' does not have any field named 'a'
   14 |         : a{2}
      |           ^
Run Code Online (Sandbox Code Playgroud)

c++ templates derived-class mixins

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

什么是 void() 纯右值以及如何使用它?

阅读 cppreference 对函数式风格转换的描述,我偶然发现了以下解释void()

如果 target-type 是(可能是 cv 限定的)void,则表达式是没有结果对象的 void 纯右值 (C++17 起)

现在我明白我可以void()像这样创建纯右值,但是我可以用它做什么以及为什么这可能?

c++ casting void

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