通过使用这样的restrict关键字:
int f(int* restrict a, int* restrict b);
Run Code Online (Sandbox Code Playgroud)
我可以指示编译器数组a和b不重叠.说我有一个结构:
struct s{
(...)
int* ip;
};
Run Code Online (Sandbox Code Playgroud)
并编写一个带有两个struct s对象的函数:
int f2(struct s a, struct s b);
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我怎样才能类似地指示编译器a.ip并且b.ip不重叠?
我一直在尝试为std :: cout编写一个线程安全的包装器,并认为这是学习一些可变参数模板的好时机.
然后,当我认为我做对了,我注意到它与std :: endl不兼容.
拿这个代码:
template <typename... P>
void f(P...){}
int main()
{
f(1,2,3,std::endl);
}
Run Code Online (Sandbox Code Playgroud)
当你尝试编译它时,GCC以一种非常愚蠢的方式抱怨:
main.cpp:18:19: error: too many arguments to function 'void f(P ...) [with P = {}]'
Run Code Online (Sandbox Code Playgroud)
当您使用常规模板尝试时,您会得到
main.cpp:22:13: error: no matching function for call to 'f(<unresolved overloaded function type>)'
Run Code Online (Sandbox Code Playgroud)
这实际上是有道理的.
这对我来说不是一个大问题,我可以用其他方式来做,但我真的想知道是否有办法绕过这个限制.
是否可以编写可变版本的std::is_convertible?例如are_convertible<T1, T2, T3, T4>会返回is_convertible<T1, T3> && is_convertible<T2, T4>.我一直在考虑这个问题几个小时但是无法提出任何合理的建议.
澄清我想使用它有点像这样:
template <class ...Args1>
struct thing
{
template <class ...Args2>
enable_if_t<are_convertible<Args2..., Args1...>::value>
foo(Args2 &&...args){}
}
Run Code Online (Sandbox Code Playgroud) 在将char数组转换为其他类型时,我对严格的别名规则感到困惑.我知道允许将任何对象转换为char数组,但我不确定反过来会发生什么.
看看这个:
#include <type_traits>
using namespace std;
struct{
alignas (int) char buf[sizeof(int)]; //correct?
} buf1;
alignas(int) char buf2[sizeof(int)]; //incorrect?
struct{
float f; //obviously incorrect
} buf3;
typename std::aligned_storage<sizeof(int), alignof(int)>::type buf4; //obviously correct
int main()
{
reinterpret_cast<int&>(buf1) = 1;
*reinterpret_cast<int*>(buf2) = 1;
reinterpret_cast<int&>(buf3) = 1;
reinterpret_cast<int&>(buf4) = 1;
}
Run Code Online (Sandbox Code Playgroud)
使用g ++ - 5.3.0进行编译只会在main的第二行和第三行产生警告:
$ g++ -fsyntax-only -O3 -std=c++14 -Wall main.cpp
main.cpp: In function ‘int main()’:
main.cpp:25:30: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
*reinterpret_cast<int*>(buf2) = 1;
^ …Run Code Online (Sandbox Code Playgroud) 看看这段代码:
#include <iostream>
using namespace std;
#define foo bar
#define string(a) #a
#define concat(a,b) string(a ## b)
#define concat2(a,b) concat(a,b)
int main()
{
cout << concat(foo, baz) << '\n' << concat2(foo, baz) << endl;
}
Run Code Online (Sandbox Code Playgroud)
该程序的输出是:
foobaz
barbaz
Run Code Online (Sandbox Code Playgroud)
为什么添加额外级别的间接会改变此代码的行为?
根据http://en.cppreference.com/w/cpp/utility/tuple/tuple,std::tuple不能在C ++ 17之前隐式构造。他们甚至举了一个例子来证明这一点:
std::tuple<int, int> foo_tuple()
{
return {1, -1}; // Error until C++17
return std::make_tuple(1, -1); // Always works
}
Run Code Online (Sandbox Code Playgroud)
但是,同时使用gcc 6.2和clang 3.8.1,我可以在C ++ 11和C ++ 14模式下干净地编译此代码:
piotrek@piotrek-Inspiron-5423:~/test$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/6/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 6.2.0-5ubuntu12' --with-bugurl=file:///usr/share/doc/gcc-6/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-6 --program-prefix=x86_64-linux-gnu- --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --enable-default-pie --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-6-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-6-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-6-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar …Run Code Online (Sandbox Code Playgroud) 这是代码:
#include <utility>
#include <type_traits>
template <class T>
class ClassWithDisabledFoo
{
public:
template <class U = T, std::enable_if_t<std::is_integral<U>::value, int> = 0>
void foo(){}
};
class ClassWithFoo
{
public:
void foo(){}
};
class Derived: public ClassWithFoo, public ClassWithDisabledFoo<double>
{
};
void test()
{
Derived d;
d.foo();
}
Run Code Online (Sandbox Code Playgroud)
在调用时d.foo(),clang 和 gcc 都表示调用foo是不明确的,尽管ClassWithDisabledFoo::foo被enable_if. 如果我将foo定义从移动ClassWithFoo到Derived,代码就会编译。
为什么这不起作用,我怎样才能使它起作用?