在GCC上用C++ 11进行可变参数模板编程时,偶尔会出现一个错误,上面写着"抱歉,未实现:不能将'Identifier ...'扩展到固定长度的列表中." 如果我删除代码中的"...",那么我会得到一个不同的错误:"错误:参数包没有用'...'扩展".
因此,如果我有"...",GCC会调用该错误,如果我取出"......",GCC也会调用该错误.
我能够处理这个问题的唯一方法是使用不同的方法从头开始完全重写模板元程序,并且(幸运的是)我最终提出了不会导致错误的代码.但我真的很想知道我做错了什么.尽管使用谷歌搜索,尽管进行了大量实验,但我无法确定在产生此错误的可变参数模板代码与没有错误的代码之间做出不同的反应.
错误消息的措辞似乎暗示代码应该按照C++ 11标准工作,但GCC还不支持它.或者它可能是一个编译器错误?
这是产生错误的一些代码.注意:我不需要您为我编写正确的实现,而只是指出导致此特定错误的代码是什么
// Used as a container for a set of types.
template <typename... Types> struct TypePack
{
// Given a TypePack<T1, T2, T3> and T=T4, returns TypePack<T1, T2, T3, T4>
template <typename T>
struct Add
{
typedef TypePack<Types..., T> type;
};
};
// Takes the set (First, Others...) and, while N > 0, adds (First) to TPack.
// TPack is a TypePack containing between 0 and N-1 types.
template <int N, typename …Run Code Online (Sandbox Code Playgroud) 我有一个C++程序,我用mingw编译(gcc for Windows).使用包含gcc 4.4.1的mingw的TDM版本.可执行文件链接到两个静态库(.a)文件:它们是用C编写的第三方库; 另一个是由我编写的C++库,它使用C库提供我自己的C++ API.
在我看来,(在我看来,过多)部分C库的功能是在内联函数中实现的.当你使用C库的API时,你无法避免包含内联函数,但当我尝试将它们全部链接在一起时,我会收到链接错误,说明所有内联函数都有多个定义 - 我都有在我的C++包装器库中调用,而我没有调用它,基本上在头文件中内联定义的任何内容都在C库和C++库中为它创建了一个函数.
当包含文件在同一项目中的不同.c或.cpp文件中多次使用时,它不会导致多个定义错误; 问题只是它为每个库生成一个定义.
编译器如何/为什么在两个库中为这些内联函数生成函数和符号?如何强制它停止在我的代码中生成它们?是否有一个工具可以运行以从.a文件中删除重复的函数,或者是一种使链接器忽略多个定义的方法?
(仅供参考,第三方库在其所有标题中都包含#ifdef __cplusplus和extern"C"保护;无论如何,如果这是问题,它不会导致符号的多重定义,它会导致相反的问题,因为符号会不确定或至少不同.)
值得注意的是,如果我链接到第三方C库的DLL,则不会发生链接错误; 然而,我得到奇怪的运行时故障似乎与我的代码有关,它应该从DLL调用自己的函数版本.(好像编译器正在创建我没有要求的本地版本的函数.)
之前已经问过这个问题的类似版本,但是,我没有找到任何这些问题的答案:
这个问题的答案是海报是多个定义变量,我的问题是内联函数的多重定义: 重复多重定义错误在多个cpps中包含相同的标题
这是一个MSVC计划,但我正在使用mingw; 另外,海报在这个问题中的问题是在标题中类主体之外定义C++类构造函数,而我的问题是内联的C函数: 静态Lib多重定义问题
这个傻瓜将他的所有C代码重命名为C++文件,他的C代码不是C++ - 安全:链接时 多个std :: functions的多个定义
这个只是想知道为什么违反一个定义规则不是错误: 具有不同定义的内联函数的不可预测的行为
我们有一个REST API,它已经在控制器路由中使用"/ v1 /",我们计划创建一个"/ v2 /"路径并利用Web API 2.我能够找到很多关于版本控制的信息您的控制器(属性路由,自定义解析器等),但我无法找到任何文章的一件事是版本化您的模型对象(也称为数据传输对象).人们如何对他们的Model对象进行版本控制?
在我们的代码库和问题域中,控制器是"简单的"(CRUD,真的),它是模型对象,它们编码我们的领域专业知识,我们的核心业务逻辑在其上运行.(我怀疑这对于许多应用程序都是如此,所以很奇怪大多数关于Web API 2和版本控制的网络文章都集中在控制器上,并且忽略了对Model对象的关注,好像他们会照顾好自己.)
在一个完美的世界中,我希望能够为两个API版本使用相同的类,并将属性放在属性中以包含或排除它们,例如"仅版本1","仅版本2+","在版本2中弃用了"等等.我想我可以用一个查找我创建的属性类的自定义序列化程序来实现它,但我想知道在我滚动之前是否有对它的内置支持或者它的开源库拥有.
另一种可能的方法是从版本1模型类派生版本2模型类,但我只能添加这种方式而不能删除任何东西.我可以从基类派生版本1和版本2类,但是这些基于继承的方法中的任何一个都需要A)重构类的地方加上B)工厂模式,以便内部可以创建正确的派生类型.我想避免这种情况,但仍然更喜欢它而不是代码重复.
我想另一种方法是我们可以隐藏我们真实的Model对象并将它们的值复制到界面上的"哑"数据传输对象中.这种方法很简单,具有最大的灵活性,但也可以最大化工作.
有没有我错过的选项?其他人使用什么方法?
我正在开发一个使用lambdas来描述表达式术语范围的库.因为库必须分发唯一的整数以标识每个变量,所以如果库(而不是用户)构造变量并且用户代码将它们作为lambda参数接收,则它是理想的.
(换句话说,我正在实现miniKanren的"call\fresh"的C++模拟.)
由于用户可能想要在特定范围内从零到多个新变量引入任何数字,我希望用户能够将具有不同数量参数的lambdas传递给库.但是,我不知道任何(简单的)方法(在C++ 14中)推导出任意lambda对象的参数数量.
我想到为什么不向lambda传递一个固定数量(比方说10)的variable-id参数,并让用户代码在lambda中使用省略号忽略不需要的那些?像这样的东西:
auto no_args = call_fresh([](...) { return success(); });
auto one_arg = call_fresh([](var A, ...) { return A == 1; });
auto two_args = call_fresh([](var A, var B, ...) { return A == 1 && B == 2; });
Run Code Online (Sandbox Code Playgroud)
编译器浏览器似乎接受lambda参数列表中的省略号,至少使用gcc.
它将被称为这样的东西(注意代码如何总是传递10个变量id,无论"f"是否只命名其中一个,两个或没有):
template <typename F>
auto call_fresh(F f)
{
return [f](StateCounter sc) {
return f(sc+0,sc+1,sc+2,sc+3,sc+4,
sc+5,sc+6,sc+7,sc+8,sc+9);
};
}
Run Code Online (Sandbox Code Playgroud)
虽然这是我感到惊讶的一个功能,有没有理由不使用带椭圆的lambdas?
在Base构造函数的C++中,'this'的实际类型是'Base'而不是'Derived',因此调用虚函数是不安全的.但是,基类在基础构造期间将 'this' 的值传递给将在构造完成后将来调用虚函数的回调对象是否安全?
给定C++函数f(X x),其中x是类型X的变量,类型Y的变量y,C++编译器将对y执行的所有自动/隐式转换是什么,以便语句"f(y) ;" 是合法代码(没有错误,没有警告)?
例如:
传递派生和功能获取基础& - 确定传递基础&功能派生& - 没有投射传递不能正常功能需要长时间 - 确定,创建一个临时长传递int和函数需要很长时间& - 不行,参考临时
注意内置类型与类相比如何有一些怪癖:一个Derived可以传递给函数接受一个Base(虽然它被切片),并且一个int可以传递给函数花费很长时间,但你不能传递一个int&to一个功能需要很长时间!!
什么是总是"正常"的完整案例列表(不需要使用任何演员来做)?
它是什么:我有一个C++脚本绑定库,它允许您绑定C++代码,它将在运行时基于脚本表达式调用C++函数.由于表达式是在运行时计算的,因此必须提前预期可能需要在表达式中使用的源类型和函数参数类型的所有合法组合,并在库中进行预编译,以便它们在运行时可用.如果我错过了一个合法的组合,一些合理的表达式将不适用于运行时表达式; 如果我意外地生成一个不合法的C++组合,我的库就不会编译.
编辑(缩小问题):
谢谢,你的所有答案实际上都非常有用.我知道答案很复杂,但听起来我只是看到了冰山一角.
让我稍微改一下这个问题然后限制它的范围:我将让用户指定一个"BaseClasses"列表和一个"UserDefinedConversions"列表.对于Bases,我将生成包括引用和指针转换在内的所有内容.但是我可以从UserDefined Conversions列表安全地做什么情况(const/reference/pointer)?(用户将提供裸类型,我将在模板中使用*,&,const等进行装饰.)
如果在头文件中有函数的内联定义,并且想要将函数定义体移出标题并转换为.cpp文件,则不能只按照定义的方式剪切和粘贴函数.标题; 你必须从这里转换语法:
class Foo
{
void method1() { definition(); }
void method2() { definition(); }
void method3() { definition(); }
};
Run Code Online (Sandbox Code Playgroud)
对此:
void Foo::method1() { definition(); }
void Foo::method2() { definition(); }
void Foo::method3() { definition(); }
Run Code Online (Sandbox Code Playgroud)
编辑:只是想指出我希望避免的是必须在每个方法名称前面键入类名.这似乎是一件小事,但当你将大量的函数定义移出标题并进入cpp文件时,它就会增加.当返回类型特别复杂时,您必须找到每个返回类型结束并且每个方法名称开始的行.
所以我的问题是,我是否必须像上面的第二段代码那样做?如果我这样做会是什么(符合以下标准的C++?):
在Foo.h中:
class Foo
{
void method1();
void method2();
void method3();
};
Run Code Online (Sandbox Code Playgroud)
在Foo.cpp中:
#include "Foo.hpp"
class Foo
{
void method1() { definition(); }
void method2() { definition(); }
void method3() { definition(); }
};
Run Code Online (Sandbox Code Playgroud)