考虑下面粘贴的代码.我已经定义了一个非常简单的类,编译器为其生成一个隐式推理指南,因此可以在没有显式模板参数的情况下构造它.但是,模板参数推导不适用于从简单别名模板构造对象,该模板仅直接转发到目标类:
template< typename A, typename B >
struct Foo {
Foo( A const &a, B const &b )
: a_(a), b_(b)
{ }
A a_;
B b_;
};
template< typename A, typename B >
using Bar = Foo<A, B>;
auto foobar() {
Foo r{1, 2};
Bar s{3, 4};
// ../src/geo/vector_test_unit.cpp: In function 'auto foobar()':
// ../src/geo/vector_test_unit.cpp:16:6: error: missing template arguments before 's'
// Bar s{3, 4};
// ^
return 1;
}
Run Code Online (Sandbox Code Playgroud)
正如您从上面的代码注释中看到的那样,g ++给出了一个关于在没有模板参数的情况下使用别名模板的错误.我希望在这样的实例中转发模板参数推导.
所以,我的问题:这是通过表达模板参数演绎提案的当前措辞的明确设计吗?或者这是该功能的当前g ++实现中未完成的功能还是错误?对于提案的作者或C++ ISO委员会来说,这将是一个更大的问题,但如果其中任何一个人看到这一点:是否希望该功能的最终措辞包括启用别名模板,例如是否为他们生成了隐含指南?
我可以理解,因为别名模板可以有任何类型的模板参数,编译器可能并不总是能够成功推导出目标类模板参数,但在这种情况下,我希望编译器能够在它可以直接用于目标类. …
我有一种情况,函数必须返回从表中获取的值.此表中的单元格(假设表格正常工作......)可能包含值,或者可能不包含值.该值也可以是以下几种类型之一:( int, double, string, date但没有其他类型).
这样的函数会返回什么?回来是个好主意std::optional<std::variant<std::string, int, double, std::chrono::time_point>>吗?
那会是一个很好的使用optional和variant?
(有关我正在使用的特定版本的Boost和Clang的信息,请参阅问题的结尾)
使用新的实验性-fmodules功能在master/HEAD中编译Clang,使用下面显示的命令行选项编译以下文件时出现构建错误:
#include <iterator>
#include <boost/move/iterator.hpp>
Run Code Online (Sandbox Code Playgroud)
编译命令和错误:
anhall@leviathan: <path-to-clang-install-from-master>/bin/clang++ -o file.o -c file.cpp --std=c++1z -stdlib=libc++ -fmodules
In file included from file.cpp:2:
In file included from /usr/local/include/boost/move/iterator.hpp:27:
/usr/local/include/boost/move/detail/iterator_traits.hpp:60:17: error: reference to 'random_access_iterator_tag' is ambiguous
typedef std::random_access_iterator_tag iterator_category;
^
/Users/anhall/impersonal/code/llvm-reflexpr/install/bin/../include/c++/v1/iterator:438:30: note: candidate found by name lookup is 'std::__1::random_access_iterator_tag'
struct _LIBCPP_TYPE_VIS_ONLY random_access_iterator_tag : public bidirectional_iterator_tag {};
^
/usr/local/include/boost/move/detail/iterator_traits.hpp:34:8: note: candidate found by name lookup is 'std::random_access_iterator_tag'
struct random_access_iterator_tag;
^
/usr/local/include/boost/move/detail/iterator_traits.hpp:71:17: error: reference to 'random_access_iterator_tag' is ambiguous
typedef std::random_access_iterator_tag iterator_category;
^
/Users/anhall/impersonal/code/llvm-reflexpr/install/bin/../include/c++/v1/iterator:438:30: …Run Code Online (Sandbox Code Playgroud) 我的目标是创建一个解决方法,以便我可以在Boost Spirit Qi语义操作中使用C++ 11 lambdas,同时仍然可以访问更多扩展的qi占位符集,例如qi :: _ pass或qi :: _ r1,必须从上下文对象手动提取它们.我希望避免为一些非平凡的解析逻辑编写Phoenix lambdas,更喜欢C++ 11 lambdas中更直接的C++语法和语义.
下面的代码代表了我有一个解决方法的想法.我的想法是使用phoenix :: bind绑定到lambda并将它传递给我需要的特定占位符.但是,我得到了一个极长的模板编译器错误(gcc 4.7.0,Boost 1.54),我没有专业知识来解释.我选择了我认为最相关的部分并将其发布在代码下方.
我想知道我是否可以使用Boost Spirit在此代码中尝试做什么,如果有人能为我解释错误消息并告诉我出了什么问题.
#include <string>
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace spirit = boost::spirit;
namespace phoenix = boost::phoenix;
int main() {
std::string input{"test1 test2 test3 FOO!"};
typedef decltype(input.begin()) StringIter;
qi::rule<StringIter, std::string()> parser =
*(
qi::char_
[
phoenix::bind(
[] (char value) {
std::cerr << value << std::endl;
},
qi::_1
)
]
);
qi::parse(input.begin(), input.end(), parser);
}
Run Code Online (Sandbox Code Playgroud)
(注意:我知道这个代码执行的特定任务对于直接的Phoenix结构会更简单,或者甚至可以通过Boost Spirit更新直接允许单参数C++ …
-fmodules当使用下面所示的命令进行编译时,以下简单的测试用例文件给了我一个编译时错误,提示来自 Clang 的 github 镜像的“master” 。我想知道这是否是 Clang 的新实验性模块功能的一个错误——可能是标准库模块映射的实现问题——或者我是否做错了什么。-fbuiltin-module-map如果我添加到命令中,错误仍然出现。stdint.h有趣的是,如果我替换为 ,该错误就不再出现cstdint。
#include <stdint.h>
uint64_t foo;
Run Code Online (Sandbox Code Playgroud)
这是我的编译命令,带有错误消息:
anhall@leviathan: /Users/anhall/impersonal/code/llvm-reflexpr/install/bin/clang++ -o module-uint64_t-test.o -c module-uint64_t-test.cpp --std=c++1z -fmodules
module-uint64_t-test.cpp:3:1: error: missing '#include <_types/_uint64_t.h>'; declaration of 'uint64_t' must be imported from module 'Darwin.POSIX._types._uint64_t' before it is
required
uint64_t foo;
^
/usr/include/_types/_uint64_t.h:31:28: note: previous declaration is here
typedef unsigned long long uint64_t;
Run Code Online (Sandbox Code Playgroud)
有关我正在使用的构建的信息:它来自 Matus Chochlik 的 github Clang 镜像的分支;但我设置为与原始 clang git 镜像中“master”的(当时)头相对应的提交(换句话说,它不包括来自 Matus Chochlik 的功能“reflexpr”分支的提交):
anhall@leviathan: /Users/anhall/impersonal/code/llvm-reflexpr/install/bin/clang++ -v
clang version 4.0.0 …Run Code Online (Sandbox Code Playgroud) 我正在一个新项目中使用 Concepts TS。我的问题与结构模板和我想要创建的关联概念之间的看似循环依赖有关。该概念的具体逻辑是检查该概念的类型参数是否是结构模板的特化。由于我希望该概念可在结构模板内部使用,因此我显然需要在结构模板之前定义该概念,但概念的逻辑也需要了解结构模板。我已经通过前向声明结构模板Vector,然后定义概念VectorSpecialization,最后定义结构模板,找到了可以编译的东西Vector。requires我的具体问题与我使用结构模板的子句有关;当我转发声明它时,编译器会给我一个错误,除非我复制完整的requires子句。(参见下面的代码)。
我的具体问题是:有没有办法避免requires模板的前向声明和定义之间的子句完全重复?一种可能性是将子句的逻辑分解requires为声明和定义都可以委托给的公共实体,我认为这将解决 DRY 原则;但我很好奇我是否可以在这里做出更高级别的结构决策,以避免requires在两个地方都需要一个子句,或者是否有一种更惯用的方式在这样的用例中使用概念,我可以从中受益从。重申一下,我所说的用例是:编写一个将在模板中使用的概念,但该概念还需要了解模板。
// Forward declare the struct template so that the concept can refer to it
// Note the need to repeat the 'requires' clause. Can that repetition be
// be avoided?
template< typename T, size_t N > requires N > 1 struct Vector;
// compile-time overload set using template arg deduction to detect
// …Run Code Online (Sandbox Code Playgroud) c++ ×6
c++17 ×4
c++-modules ×2
clang++ ×2
boost ×1
boost-spirit ×1
c++-concepts ×1
c++11 ×1
lambda ×1
libc++ ×1
optional ×1
variant ×1