C++ 如何使用以“constexpr”声明的结构作为模板参数?

C++ 如何使用以“constexpr”声明的结构作为模板参数?,c++,c++14,C++,C++14,图像您有一个结构,如下所示: typedef struct { int a; int b[2]; int c; } DataParameters; 在特定情况下,您在编译时知道所有这些值: constexpr DataParameters p = { .a = 5, .b = {3, 3}, .c = 12 }; 然后,您需要创建一个使用a、b、c值的模板函数。以下语法有效,因为结构声明为constexpr 但是假设您有一个更大的结构,并且您不

图像您有一个结构,如下所示:

typedef struct {
    int a;
    int b[2];
    int c;
} DataParameters;
在特定情况下,您在编译时知道所有这些值:

constexpr DataParameters p = {
    .a = 5,
    .b = {3, 3},
    .c = 12
};
然后,您需要创建一个使用a、b、c值的模板函数。以下语法有效,因为结构声明为constexpr

但是假设您有一个更大的结构,并且您不需要一个庞大的模板参数列表。有没有更好的办法?我尝试了以下操作,但出现了编译器错误:

template<const DataParameters& P>
void doSomething() {
    ...
}

doSomething<p>();
有什么建议吗?

自从C++11以来,您可以使用带有静态存储持续时间和外部或内部链接的对象的模板

由于C++17,您可以使用带有静态存储持续时间的对象的模板,链接限制被删除

由于C++20,您可以使用模板。非类型参数可以是C++20之后的:

具有以下属性的文字类类型: 所有基类和非静态数据成员都是公共的、不可变的和 所有基类和非静态数据成员的类型都是结构类型或可能是其多维数组。 由于C++11,您可以使用具有静态存储持续时间和外部或内部链接的对象的模板

由于C++17,您可以使用带有静态存储持续时间的对象的模板,链接限制被删除

由于C++20,您可以使用模板。非类型参数可以是C++20之后的:

具有以下属性的文字类类型: 所有基类和非静态数据成员都是公共的、不可变的和 所有基类和非静态数据成员的类型都是结构类型或可能是其多维数组。
无关:删除C样式类型定义。如果DataParameters是您想要的类型,请执行struct DataParameters{…};它是一种类型。对我有效:无关:删除C风格的类型定义。如果DataParameters是您想要的类型,请执行struct DataParameters{…};这是一种类型。对我有效:从C++98开始就允许使用引用模板参数,尽管可能对如何使用它们有一些限制。@Brian我在godbolt上试过,但这个示例在C++14上无法编译。也许ref类型以前必须是整数?@Brian我已经做了更多的测试并编辑了答案。似乎在C++98中,对象必须有外部链接,我猜这意味着静态存储持续时间,因为thread_local还不存在。在C++11中,它必须具有静态存储持续时间和外部或内部链接。在C++17中,链接限制被删除。@Brian,谢谢。我已将此信息添加到答案中。这是非常有用的。自C++98以来就允许使用引用模板参数,尽管在如何使用这些参数方面可能有一些限制。@Brian我在godbolt上试过,但这个示例在C++14上无法编译。也许ref类型以前必须是整数?@Brian我已经做了更多的测试并编辑了答案。似乎在C++98中,对象必须有外部链接,我猜这意味着静态存储持续时间,因为thread_local还不存在。在C++11中,它必须具有静态存储持续时间和外部或内部链接。在C++17中,链接限制被删除。@Brian,谢谢。我已将此信息添加到答案中。这很有帮助。
template<const DataParameters& P>
void doSomething() {
    ...
}

doSomething<p>();
struct DataParameters // don't use C style typedef
{
    int a;
    int b[2];
    int c;
};

template <const DataParameters& x>
void foo() {}

constexpr DataParameters gp{};

void test_ref_global()
{
    foo<gp>(); // ok since C++11
}

void test_ref_local()
{
    static constexpr DataParameters p{};    
    foo<p>(); // ok since C++17
}

template <DataParameters x> // ok since C++20
void bar() {}

auto test_val()
{
    constexpr DataParameters p{};
    bar<p>(); // ok since C++20
}