是否可以编写一个C++(0x)元函数来确定一个类型是否可调用?
通过可调用类型我的意思是函数类型,函数指针类型,函数引用类型(这些被检测到boost::function_types::is_callable_builtin),lambda类型,以及任何具有重载的类operator()(也许任何类具有隐式转换运算符到其中一个,但这不是绝对有必要).
编辑:元函数应检测operator()任何签名的存在,包括模板化operator().我相信这是困难的部分.
编辑:这是一个用例:
template <typename Predicate1, typename Predicate2>
struct and_predicate
{
template <typename ArgT>
bool operator()(const ArgT& arg)
{
return predicate1(arg) && predicate2(arg);
}
Predicate1 predicate1;
Predicate2 predicate2;
};
template <typename Predicate1, typename Predicate2>
enable_if<ice_and<is_callable<Predicate1>::value,
is_callable<Predicate2>::value>::value,
and_predicate<Predicate1, Predicate2>>::type
operator&&(Predicate1 predicate1, Predicate2 predicate2)
{
return and_predicate<Predicate1, Predicate2>{predicate1, predicate2};
}
Run Code Online (Sandbox Code Playgroud)
is_callable 是我想要实现的.
如果我在运行时重新编译可执行文件会发生什么?操作系统在开始运行时是否将所有可执行文件的内容读入内存,因此它永远不会读取新的可执行文件?或者它会读取新的可执行文件的部分,认为它没有改变,导致可能未定义的行为?
如果我运行的脚本在循环中重复调用可执行文件,并且在脚本运行时重新编译可执行文件,该怎么办?是否保证循环的未来迭代将调用新的可执行文件,并且只有在进行切换时正在进行的调用的结果可能已损坏?
我的操作系统是Linux,但我也很好奇Windows上会发生什么.
我一直在阅读有关C++模块提案(最新草案)的内容,但我并不完全了解它旨在解决的问题.
它的目的是允许由一个编译器构建的模块被任何其他编译器使用(当然,在相同的OS /架构上)?也就是说,提案是否相当于标准化C++ ABI?
如果没有,是否有另一个提议被认为是标准化C++ ABI并允许编译器互操作?
boost :: date_time和std :: chrono的互操作性如何?
例如,有没有办法在boost :: posix_time :: ptime和std :: chrono :: time_point之间进行转换?
我尝试搜索有关此类转换的文档,但找不到任何内容.
可以将push_back不可复制但可移动类型的rvalues转换为该类型的向量:
#include <vector>
struct S
{
S(int);
S(S&&);
};
int main()
{
std::vector<S> v;
v.push_back(S(1));
v.push_back(S(2));
v.push_back(S(3));
}
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试初始化列表构造具有相同rvalues的向量时,我得到关于所需的复制构造函数的错误:
#include <vector>
struct S
{
S(int);
S(S&&);
};
int main()
{
std::vector<S> v = {S(1), S(2), S(3)};
}
Run Code Online (Sandbox Code Playgroud)
我在GCC 4.7中遇到以下错误:
In file included from include/c++/4.7.0/vector:63:0,
from test.cpp:1:
include/c++/4.7.0/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = S, _Args = {const S&}]':
include/c++/4.7.0/bits/stl_uninitialized.h:77:3: required from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = const S*, _ForwardIterator = S*, …Run Code Online (Sandbox Code Playgroud) 我刚刚阅读了关于C11的维基百科文章,这是2011年12月发布的C标准的新版本,我看到其中一个增加的功能是"类型通用表达式":
使用
_Generic关键字的类型泛型表达式.例如,下面的宏CBRT(X)转换为cbrtl(X) ,CBRT(X)或cbrtf(X) 取决于类型X:Run Code Online (Sandbox Code Playgroud)#define cbrt(X) _Generic((X), long double: cbrtl, \ default: cbrt, \ float: cbrtf)(X)
这看起来非常糟糕 - 如果他们要改变语言,为什么不像C++一样添加函数重载?
clang和gcc在以下代码的行为上有所不同:
struct foo
{
foo(int);
};
struct waldo
{
template <typename T>
operator T();
};
int main()
{
waldo w;
foo f{w};
}
Run Code Online (Sandbox Code Playgroud)
clang接受此代码,并foo(int)调用构造函数.但是,gcc抱怨foo(int)构造函数和隐式生成的复制和移动构造函数之间存在歧义:
test.cpp: In function 'int main()':
test.cpp:15:12: error: call of overloaded 'foo(<brace-enclosed initializer list>)' is ambiguous
foo f{w};
^
test.cpp:15:12: note: candidates are:
test.cpp:3:5: note: foo::foo(int)
foo(int);
^
test.cpp:1:8: note: constexpr foo::foo(const foo&)
struct foo
^
test.cpp:1:8: note: constexpr foo::foo(foo&&)
Run Code Online (Sandbox Code Playgroud)
谁是对的?
值得注意的foo f{w}是,如果更改为foo f(w)(注意从大括号到括号的更改),gcc和clang都会出错.这让我希望gcc对上面例子的行为(即给出错误)是正确的,否则初始化()和{}形式之间会出现奇怪的不一致.
编辑 …
如何std::array从范围初始化(由一对迭代器定义)?
像这样的东西:
vector<T> v;
...
// I know v has exactly N elements (e.g. I just called v.resize(N))
// Now I want a initialized with those elements
array<T, N> a(???); // what to put here?
Run Code Online (Sandbox Code Playgroud)
我以为array会有一个构造函数接受一对迭代器,所以我可以做array<T, N> a(v.begin(), v.end()),但它似乎根本没有构造函数!
我知道我可以copy将矢量放入数组中,但我宁愿直接用矢量内容初始化数组,而不是先默认构造它.我怎么能够?
我最近偶然发现了以下关于const-correctness的"漏洞":
struct Inner {
int field = 0;
void Modify() {
field++;
}
};
struct Outer {
Inner inner;
};
class MyClass {
public:
Outer outer;
Inner& inner; // refers to outer.inner, for convenience
MyClass() : inner(outer.inner) {}
void ConstMethod() const {
inner.Modify(); // oops; compiles
}
};
Run Code Online (Sandbox Code Playgroud)
它似乎有可能使用这个漏洞来修改声明为的对象const,我认为这是未定义的行为:
int main() {
const MyClass myclass;
std::cout << myclass.outer.inner.field << "\n"; // prints 0
myclass.ConstMethod();
std::cout << myclass.outer.inner.field << "\n"; // prints 1
}
Run Code Online (Sandbox Code Playgroud)
这让我很害怕,因为我似乎只是调用了一个与const-correctness相关的未定义行为,这个行为不使用const_cast或使用C风格的强制转换去掉constness .
所以,我的问题是: …
对于以下代码:
struct foo {};
struct A
{
typedef foo foo_type;
void foo();
};
Run Code Online (Sandbox Code Playgroud)
GCC给出了一个编译器错误:
test.cpp:7:14: error: declaration of 'void A::foo()' [-fpermissive]
void foo();
^
test.cpp:1:8: error: changes meaning of 'foo' from 'struct foo' [-fpermissive]
struct foo {};
^
Run Code Online (Sandbox Code Playgroud)
但clang接受它没有编译器错误.谁是对的?
请注意,如果删除typedef或将其更改为typedef ::foo foo_type,则gcc和clang都接受该代码.