标准或某些提升库是否提供编译时间变体?

发布于 2025-02-11 20:55:51 字数 1082 浏览 1 评论 0原文

我不是在问如何在编译时间期间,在给定索引上获取std ::变体成员的类型

我询问标准或某些Boost库是否提供std :: variant类似的类,其包含类型是在编译时已知的。

我相信,我要问的并不是完全胡说八道,因为有 boost :: hana ::可选 扮演相同角色(如我想象的类型),但相对于 std ::可选

至于其实用程序,它将允许一个人将几个过载写入一个,例如

void f(std::string, A);
void f(std::string, B);
void f(int, A);
void f(int, B);

可以清楚地写出实现,

void f(var<std::string, int>, var<A, B>);

如果constexpr 将用于输入类型上的分支。

I'm not asking how to Get type of a std::variant member at a given index during compile time.

I'm asking whether the standard or some boost library offer a std::variant-like class whose contained type is known at compile time.

What I'm asking, I believe, is not completely nonsense, as there's boost::hana::optional which plays the same role (as the type I'm imagining), but with respect to std::optional.

As regards its utility, it would allow one to write several overloads into one, e.g.

void f(std::string, A);
void f(std::string, B);
void f(int, A);
void f(int, B);

could be written as

void f(var<std::string, int>, var<A, B>);

Clearly the implementation would make use of if constexpr to branch on the input types.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

前事休说 2025-02-18 20:55:51

C ++ 20概念和缩写模板功能以评论和Spencer的答案为基础,几乎可以为您提供所描述的内容。

#include <type_traits>
#include <string>

template <class T, class... Ts>
concept var = (std::is_same_v<T, Ts> || ...);

struct A{};
struct B{};

void f(var<int, std::string> auto a1, var<A, B> auto a2) {
    if constexpr (std::is_same_v<decltype(a1), int>) {
        // int path
    } else {
        // string path
    }
}

https://godbolt.org/z/g5wdmtdgp

Building on the comments and Spencer's answer, C++20 concepts and abbreviated template functions will give you almost exactly what you described.

#include <type_traits>
#include <string>

template <class T, class... Ts>
concept var = (std::is_same_v<T, Ts> || ...);

struct A{};
struct B{};

void f(var<int, std::string> auto a1, var<A, B> auto a2) {
    if constexpr (std::is_same_v<decltype(a1), int>) {
        // int path
    } else {
        // string path
    }
}

https://godbolt.org/z/G5WdMTdGP

活雷疯 2025-02-18 20:55:51

您已经可以使用功能模板来实现既定目标。任何类型的变体都会不必要地使事物复杂化。您将在标题中的某个位置将特征类型类型:

// one_of.h
#include <type_traits>

template <class T, class First, class...Rest>
struct one_of
{
   static_assert(std::is_same_v<std::remove_cvref_t<First>, First>);
   static constexpr bool value = std::is_same_v<std::remove_cvref_t<T>, First> 
                               || one_of<T, Rest...>::value;
};


template <class T, class First>
struct one_of<T, First>
{
   static_assert(std::is_same_v<std::remove_cvref_t<First>, First>);
   static constexpr bool value = std::is_same_v<std::remove_cvref_t<T>, First>;
};


template <class T, class...Cands>
constexpr bool one_of_v = one_of<T, Cands...>::value;

然后,在实际的程序代码中,您将使用One_of_V模板来限制(通过C ++ 20函数约束)作为参数允许的类型:

#include "one_of.h"
#include <string>

struct A{};
struct B{};

template <class A1, class A2>
requires one_of_v<A1, std::string, int> && one_of_v<A2, A, B>
void f(A1 && a1, A2 && a2)
{
   if constexpr (std::is_same_v<int, A1>)
   {
       // do int stuff
   }
   else
   {
      // guaranteed to be string, do string stuff
   }
}

int main()
{
    int d;
    A e;
    f(d, e); // matches
    std::string s;
    B b;
    f(s, b); // matches
    //double a;
    //double b;
    //f(a, b); // no match
}

现在,One_of有点ham手,我可能会在真实代码中使用更多微妙的特质类型,但这正确演示了该概念。

我亲自找到了,如果constexpr具有类型特征在减少模板功能所需的过载数方面非常有用。另外,它更简洁地解释了所有不同的情况,而彼此相邻,而不是以您无法一次理解的方式分散的过载功能。

You can already accomplish your stated goal with a function template. Any type of variant would complicate things unnecessarily. You would have a traits type somewhere in a header:

// one_of.h
#include <type_traits>

template <class T, class First, class...Rest>
struct one_of
{
   static_assert(std::is_same_v<std::remove_cvref_t<First>, First>);
   static constexpr bool value = std::is_same_v<std::remove_cvref_t<T>, First> 
                               || one_of<T, Rest...>::value;
};


template <class T, class First>
struct one_of<T, First>
{
   static_assert(std::is_same_v<std::remove_cvref_t<First>, First>);
   static constexpr bool value = std::is_same_v<std::remove_cvref_t<T>, First>;
};


template <class T, class...Cands>
constexpr bool one_of_v = one_of<T, Cands...>::value;

And then, in your actual program code, you would use the one_of_v template to restrict (via a c++20 function constraint) the types allowed as parameters:

#include "one_of.h"
#include <string>

struct A{};
struct B{};

template <class A1, class A2>
requires one_of_v<A1, std::string, int> && one_of_v<A2, A, B>
void f(A1 && a1, A2 && a2)
{
   if constexpr (std::is_same_v<int, A1>)
   {
       // do int stuff
   }
   else
   {
      // guaranteed to be string, do string stuff
   }
}

int main()
{
    int d;
    A e;
    f(d, e); // matches
    std::string s;
    B b;
    f(s, b); // matches
    //double a;
    //double b;
    //f(a, b); // no match
}

Now, one_of is a bit ham-handed and I would probably use more subtle traits types in real code, but this demonstrates the concept correctly.

I've personally found if constexpr with type traits very useful in reducing the number of overloads needed for template functions. Plus, it explains all the different cases more succinctly, all right next to each other, than overloaded functions that may be spread out in a way that you can't comprehend all at once.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文