C++ 使用非constexpr对象的静态constexpr成员变量作为模板参数
我正在编写一个库,其中使用非类型模板参数将本质上是静态的对象参数构建到类型中。这样做可以在这些值是运行时值的实现上提供大规模的性能优化(小的基准测试为10倍,预期为5-7倍)。但是,我发现C++并没有很好地支持这个习语。我正在尝试重构库,使不太熟悉模板或元编程的开发人员更容易使用它 我想提供C++ 使用非constexpr对象的静态constexpr成员变量作为模板参数,c++,templates,constexpr,C++,Templates,Constexpr,我正在编写一个库,其中使用非类型模板参数将本质上是静态的对象参数构建到类型中。这样做可以在这些值是运行时值的实现上提供大规模的性能优化(小的基准测试为10倍,预期为5-7倍)。但是,我发现C++并没有很好地支持这个习语。我正在尝试重构库,使不太熟悉模板或元编程的开发人员更容易使用它 我想提供constexpr函数来简化static constexpr成员变量的提取(用于通过类型传播静态值),这样用户就可以在不了解后台繁重机械的情况下进行一些基本的元编程。比如说, #包括 模板 课例{ 公众: 静
constexpr
函数来简化static constexpr
成员变量的提取(用于通过类型传播静态值),这样用户就可以在不了解后台繁重机械的情况下进行一些基本的元编程。比如说,
#包括
模板
课例{
公众:
静态constexpr auto C=A+B;
私人:
int b{0};
};
模板
constexpr auto getC(示例e){return decltype(e)::C;}
/****用户代码****/
int main()
{
示例e;
例f;
}
这不起作用,e
作为非constexpr可以在constexpr上下文中使用,即使您没有使用该值(奇怪的是,如果Example
没有运行时成员,它就会起作用)。人们可以编写decltype(e)::C
,但是如果它是一个引用,他们就必须std::remove\u reference::type::C
,当然,他们必须知道这样做,并且知道足够多的知识来解决像remove\u reference
调用这样的常见问题。在这一点上,对于这个库所针对的典型程序员来说,我们已经陷入了困境
constexpr
函数不起作用,宏不适用于类型系统,因此它们也不足够,否则我如何才能做到这一点?您可以使用宏来包装
std::remove_reference<decltype(C)>::type::C
std::remove\u reference::type::C
那看起来像
#define getC(obj) std::remove_reference_t<decltype(obj)>::C
#定义getC(obj)std::删除\u引用\u t::C
您可以使用宏来包装
std::remove_reference<decltype(C)>::type::C
std::remove\u reference::type::C
那看起来像
#define getC(obj) std::remove_reference_t<decltype(obj)>::C
#定义getC(obj)std::删除\u引用\u t::C
为了实现getC
,我选择了Nathan的答案和被删除的答案的组合
模板
constexpr int getC_389;(){return std::remove_reference_t::C;}
#定义getC(e)(getC_u2;()
该函数执行繁重的操作,如果由于防护装置的原因,您给它一个无效的类型,它会给出一个很好的错误消息。宏以一种自己永远不会失败的方式进行混乱的(对初学者)调用
getC(1);//错误:“C”不是“std::remove_reference::type”{aka'int}的成员
为了实现getC
,我选择了Nathan的答案和被删除的答案的组合
模板
constexpr int getC_389;(){return std::remove_reference_t::C;}
#定义getC(e)(getC_u2;()
该函数执行繁重的操作,如果由于防护装置的原因,您给它一个无效的类型,它会给出一个很好的错误消息。宏以一种自己永远不会失败的方式进行混乱的(对初学者)调用
getC(1);//错误:“C”不是“std::remove_reference::type”{aka'int}的成员
我很快就考虑到了这一点,但我不喜欢它在检查类型方面做得不多,因此您往往会收到糟糕的错误消息。被删除的答案在这方面更好,但调用很混乱。所以我选择了两者。谢谢你让我重新考虑。我很快就考虑了这个问题,但我不喜欢它在检查类型方面做得不多,所以你往往会收到糟糕的错误消息。被删除的答案在这方面更好,但调用很混乱。所以我选择了两者。谢谢你让我重新考虑。很好的解决方案。如果您想给出一个定制的错误消息NICE解决方案,您甚至可以在函数体中为静态断言切换SFINAE。如果希望给出自定义错误消息,甚至可以在函数体中为静态断言切换SFINAE