我正在尝试编写一个函数,根据枚举的运行时值将值的枚举映射到一组类型。我意识到您不能根据枚举的运行时值返回不同的类型,因为编译器不知道要分配多少堆栈空间。但是,我正在尝试将其编写为 constexpr 函数,使用新的 if-constexpr 功能来实现它。
我收到来自 clang 的错误,提示我使用了非法指定的模板参数。有人知道如何实现吗?
编辑:这是一个更容易理解的版本,更简洁地展示了我的问题: http://coliru.stacked-crooked.com/a/2b9fef340bd167a8
旧代码:
#include <cassert>
#include <tuple>
#include <type_traits>
namespace
{
enum class shape_type : std::size_t
{
TRIANGLE = 0u,
RECTANGLE,
POLYGON,
CUBE,
INVALID_SHAPE_TYPE
};
template<std::size_t T>
struct shape {
};
using triangle = shape<static_cast<std::size_t>(shape_type::TRIANGLE)>;
using rectangle = shape<static_cast<std::size_t>(shape_type::RECTANGLE)>;
using polygon = shape<static_cast<std::size_t>(shape_type::POLYGON)>;
using cube = shape<static_cast<std::size_t>(shape_type::CUBE)>;
template<std::size_t A, std::size_t B>
static bool constexpr same() noexcept { return A == B; }
template<std::size_t ST>
static auto constexpr make_impl(draw_mode const dm)
{
if constexpr (same<ST, shape_type::TRIANGLE>()) {
return triangle{};
} else if (same<ST, shape_type::RECTANGLE>()) {
return rectangle{};
} else if (same<ST, shape_type::POLYGON>()) {
return polygon{};
} else if (same<ST, shape_type::CUBE>()) {
return cube{};
} else {
assert(0 == 5);
}
}
static auto constexpr make(shape_type const st, draw_mode const dm)
{
switch (st) {
case shape_type::TRIANGLE:
return make_impl<shape_type::TRIANGLE>(dm);
case shape_type::RECTANGLE:
return make_impl<shape_type::RECTANGLE>(dm);
case shape_type::POLYGON:
return make_impl<shape_type::POLYGON>(dm);
case shape_type::CUBE:
return make_impl<shape_type::CUBE>(dm);
case shape_type::INVALID_SHAPE_TYPE:
assert(0 == 17);
}
}
} // ns anon
////////////////////////////////////////////////////////////////////////////////////////////////////
// demo
int main()
{
}
错误:
/home/benjamin/github/BoomHS/main.cxx:42:6: warning: constexpr if is a
C++1z extension [-Wc++1z-extensions]
if constexpr (same<ST, shape_type::TRIANGLE>()) {
^ /home/benjamin/github/BoomHS/main.cxx:59:16: error: no matching function for call to 'make_impl'
return make_impl<shape_type::TRIANGLE>(dm);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /home/benjamin/github/BoomHS/main.cxx:40:23: note: candidate template
ignored: invalid explicitly-specified argument for template parameter
'ST' static auto constexpr make_impl(draw_mode const dm)
^ /home/benjamin/github/BoomHS/main.cxx:61:16: error: no matching function for call to 'make_impl'
return make_impl<shape_type::RECTANGLE>(dm);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /home/benjamin/github/BoomHS/main.cxx:40:23: note: candidate template
ignored: invalid explicitly-specified argument for template parameter
'ST' static auto constexpr make_impl(draw_mode const dm)
^ /home/benjamin/github/BoomHS/main.cxx:63:16: error: no matching function for call to 'make_impl'
return make_impl<shape_type::POLYGON>(dm);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /home/benjamin/github/BoomHS/main.cxx:40:23: note: candidate template
ignored: invalid explicitly-specified argument for template parameter
'ST' static auto constexpr make_impl(draw_mode const dm)
^ /home/benjamin/github/BoomHS/main.cxx:65:16: error: no matching function for call to 'make_impl'
return make_impl<shape_type::CUBE>(dm);
^~~~~~~~~~~~~~~~~~~~~~~~~~~ /home/benjamin/github/BoomHS/main.cxx:40:23: note: candidate template
ignored: invalid explicitly-specified argument for template parameter
'ST' static auto constexpr make_impl(draw_mode const dm)
最佳答案
是的,您的尝试是允许的。我在 N4606 中找到的两个相关摘录是:
6.4.1/2 [stmt.if]
If the if statement is of the form if constexpr [...] If the value of the converted condition is false, the first substatement is a discarded statement, otherwise the second substatement, if present, is a discarded statement.
在 constexpr if 中指示一个未采用的分支是一个废弃的语句。此外,自动函数仅考虑非丢弃的返回语句来推导返回类型
7.1.7.4/2 [dcl.spec.auto](强调我的)
[...] If the declared return type of the function contains a placeholder type, the return type of the function is deduced from non-discarded return statements, if any, in the body of the function (6.4.1).
namespace {
enum class shape_type { TRIANGLE, RECTANGLE, CIRCLE};
template<shape_type>
struct shape { };
using triangle = shape<shape_type::TRIANGLE>;
using rectangle = shape<shape_type::RECTANGLE>;
using circle = shape<shape_type::CIRCLE>;
template<shape_type ST>
constexpr auto make() {
if constexpr (ST == shape_type::TRIANGLE) {
return triangle{};
} else if constexpr (ST == shape_type::RECTANGLE) {
return rectangle{};
} else if constexpr (ST == shape_type::CIRCLE) {
return circle{};
}
}
}
int main() {
auto t = make<shape_type::TRIANGLE>();
auto r = make<shape_type::RECTANGLE>();
auto c = make<shape_type::CIRCLE>();
}
关于c++ - constexpr-if-else 主体能否在 constexpr auto 函数中返回不同类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41273101/
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行
假设我在Ruby中有这个each循环。@list.each{|i|putsiifi>10breakend}我想循环遍历列表直到满足条件。这让我感到“不像Ruby”,因为我是Ruby的新手,是否有Ruby方法可以做到这一点? 最佳答案 您可以使用Enumerable#detect或Enumerable#take_while,取决于您想要的结果。@list.detect{|i|putsii>10}#Returnsthefirstelementgreaterthan10,ornil.正如其他人所指出的,更好的风格是先进行子选择,然后再对其
导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri
如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时