我在Ubuntu 12.04上使用CERN的ROOT时偶然发现了这个非常烦人的问题,但我认为这是一个更普遍的问题.
我有一些带有外部引用的C++代码,我使用以下makefile编译和链接.在我的Mac OS X 10.8和服务器SL5上工作正常.
CXX=clang++
CXXFLAGS=-Wall -O2 -g $(shell root-config --cflags --libs)
testroot: testroot.cc
Run Code Online (Sandbox Code Playgroud)
它评估为
clang++ -Wall -O2 -g -pthread -m64 -I/opt/ROOT/5.34.05/include/root -L/opt/ROOT/5.34.05/lib/root -lCore -lCint -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lTree -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -pthread -lm -ldl -rdynamic testroot.cc -o testroot
Run Code Online (Sandbox Code Playgroud)
这给了我Ubuntu服务器上未定义的引用和链接器错误.我已经尝试过设置libs,LDFLAGS但它会产生相同的结果.当我手动编译它并将源文件和-o选项放在库之前时,它编译没有问题.
从其他线程,我认为命令的顺序可以重要,但我想知道它为什么在某些机器上,而在其他机器上没有.即使订单很重要,我认为make它足够聪明,可以自行解决.
现在的问题是:我怎样才能解决这个问题?我是否必须使用不同版本的make或ld?我必须修改我的makefile吗?
提前致谢!
以下代码正常执行(请参见此处):
#include <iostream>
struct A {
int i;
A():i(1){}
operator int&() { return i; }
};
int& rri = A();
int main()
{
int& ri = A();
std::cout << ri << '\n';
std::cout << rri << '\n';
}
Run Code Online (Sandbox Code Playgroud)
它打印
1
1
Run Code Online (Sandbox Code Playgroud)
正如所料.但是,如果我在main()中注释掉前两个语句,则只留下
std::cout << rri << '\n';
Run Code Online (Sandbox Code Playgroud)
代码打印0.
编辑:
我们假设问题出在我的代码中.但后来我问:标准中8.5.3/5中第三个要点的目的是什么,我在下面复制了:
对类型"cv1 T1"的引用由类型"cv2 T2"的表达式初始化,如下所示:
如果引用是左值引用和初始化表达式
是左值(但不是位域),"cv1 T1"与"cv2 T2"引用兼容,或者
具有类类型(即,T2是类类型),其中T1与T2不是引用相关的,并且可以转换为类型为"cv3 T3"的左值,其中"cv1 T1"与"cv3"引用兼容T3"(通过枚举适用的转换函数(13.3.1.6)并通过重载决策(13.3)选择最佳转换函数来选择此转换),
然后,引用绑定到第一种情况下的初始化表达式lvalue和第二种情况下转换的左值结果(或者,在任何一种情况下,绑定到对象的相应基类子对象).[注意:不需要通常的左值到右值(4.1),数组到指针(4.2)和函数到指针(4.3)标准转换,因此当对左值的这种直接绑定是完成. - 尾注]
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
bool m_ok = false;
void* run(void*)
{
usleep(1000000);
m_ok = true;
printf ("Good bye!\n");
return nullptr;
}
int main() {
pthread_t my_thread;
pthread_create(&my_thread, nullptr, &run, nullptr);
while (!m_ok)
continue;
printf("YES!!!\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当我用以下命令编译上面的代码时,一切都很好:
$ g++ test.cpp -lpthread -std=c++11
$ clang++ test.cpp -lpthread -std=c++11
Run Code Online (Sandbox Code Playgroud)
但是当我尝试使用优化标志时,我的程序没有完成.我测试了以下所有命令:
$ g++ test.cpp -lpthread -std=c++11 -O1
$ clang++ test.cpp -lpthread -std=c++11 -O1
$ g++ test.cpp -lpthread -std=c++11 -O2
$ clang++ test.cpp -lpthread -std=c++11 -O2
Run Code Online (Sandbox Code Playgroud)
我的g ++和clangs的版本也是:
$ g++ --version …Run Code Online (Sandbox Code Playgroud) 使用variadic模板模板参数时,要使用sizeof获取参数数量(...)GCC和Clang有不同的要求.GCC要求您填写可变参数的模板参数,而Clang要求您不要这样做.由于它们都声称符合标准,因此必须有错误或标准必须含糊不清(如果它们应在c ++ 1y中更正).
示例(http://ideone.com/5TWFKY上的完整可编辑示例):
template<template <class> class... T>
struct X
{
/* code goes here */
};
Run Code Online (Sandbox Code Playgroud)
GCC(注意:在这种情况下,Z是任何非模板类):
static const constexpr size_t count = sizeof...(T<Z>);
Run Code Online (Sandbox Code Playgroud)
铛:
static const constexpr size_t count = sizeof...(T);
Run Code Online (Sandbox Code Playgroud)
MSVC 2013(完整性 - 与Clang w/out constexpr相同,不支持):
static const size_t count = sizeof...(T);
Run Code Online (Sandbox Code Playgroud) 我在Qt创建器中有一个程序,可以在Windows机器上编译和运行.但是当我尝试在Mac OS X(10.9)中编译它时,我收到了以下消息:
Undefined symbols for architecture x86_64:
"std::__1::__basic_string_common<true>::__throw_length_error() const", referenced from:
std::__1::enable_if<__is_forward_iterator<char*>::value, void>::type std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__init<char*>(char*, char*) in libVolumeSelectorLib.a(NetCDFDataSource.o)
...
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [UI.app/Contents/MacOS/UI] Error 1
14:38:02: The process "/usr/bin/make" exited with code 2.
Error while building/deploying project VVSIT (kit: Desktop Qt 5.4.0 clang 64bit)
When executing step "Make"
Run Code Online (Sandbox Code Playgroud)
我已经尝试过再次清理和编译,以防一些Windows上构建的文件进入Mac,但事实并非如此,问题仍在继续.
我检查了这些帖子,但他们的解决方案不起作用:
不知道如何解决这个错误?
我试图用-std = c ++ 14,-std = c ++ 1z,-std = c ++ 1y设置clang-cl参数.他们不工作.我正在使用clang 3.7 pre-build for windows x64和VS 2015.
以下代码在GCC(4.9.3)和VC++(19.00.23506)中编译良好,但在Clang(3.7.0)中给出了这些错误.
错误:constexpr函数的返回类型'Foo'不是文字类型
注意:'Foo'不是字面值,因为它不是聚合,除了复制或移动构造函数之外没有constexpr构造函数
码:
#include <iostream>
#include <vector>
struct Foo
{
std::vector<int> m_vec;
Foo(const int *foo, std::size_t size=0):m_vec(foo, foo+size)
{;}
//Foo(const std::initializer_list<int> &init):m_vec{init}
//{;}
};
template <std::size_t N>
constexpr Foo make_fooArray(const int (&a)[N]) noexcept
{
return {a,N};
}
int main()
{
Foo f{ make_fooArray({1,2,3}) };
for (auto i : f.m_vec)
std::cout<< i <<" ";
std::cout<<std::endl;
}
Run Code Online (Sandbox Code Playgroud)
在rextester上运行的代码:
你能否澄清这是一个编译器错误还是我错过了什么?C++ 11标准说什么?
这是另一个案例,它在GCC和VC中编译但在Clang中不编译.
#include <iostream>
template <typename T, std::size_t N>
constexpr std::size_t sizeOf_fooArray(const T (&)[N]) noexcept
{
return N;
}
int …Run Code Online (Sandbox Code Playgroud) 考虑以下计划:
#include <iostream>
#include <algorithm>
#include <array>
bool greater_than_seven(int i) {
return i > 5;
}
bool divisible_by_five(int x) {
return ((x%5)==0);
}
int main() {
int arr[]{3,6,9,12,15};
std::cout<<"Enter a number you want to search: ";
int num;
std::cin>>num;
auto result(std::find(std::begin(arr),std::end(arr),num));
if(result != std::end(arr))
std::cout<<"arr contains: "<<num<<'\n';
else
std::cout<<"arr doesn't contain: "<<num<<'\n';
for(result=std::find_if(std::begin(arr),std::end(arr),greater_than_seven);result!=std::end(arr);++result)
std::cout<<*result<<' ';
std::cout<<'\n';
std::array<int,4> x{33,66,99,55};
for(result=std::find_if_not(std::begin(x),std::end(x),divisible_by_five);result!=std::end(x);++result)
std::cout<<*result<<'\n';
}
Run Code Online (Sandbox Code Playgroud)
这个程序在g ++和clang ++上编译得很好.
在这里查看现场演示(g ++ 5.4.0)
在这里查看现场演示(clang ++ 3.8.0)
但它在Microsoft Visual C++编译器上提供了可怕的编译器错误.
请参阅此处的实时演示(适用于x64的Microsoft(R)C/C++优化编译器版本19.00.23506)
Error(s):
source_file.cpp(27): …Run Code Online (Sandbox Code Playgroud) 以下代码包含一个fold表达式,afaiu是c ++ 17的一个功能:
template <typename... T> static bool variable_length_or(const T ... v) {
return (v || ...);
}
bool foo () {
return variable_length_or(true, false, true, false);
}
Run Code Online (Sandbox Code Playgroud)
我发现奇怪的是,在使用-std=c++14(builder-explorer)进行构建时,g ++和clang ++似乎都很好用。他们确实会发出警告:
<source>:2:16: warning: pack fold expression is a C++17 extension [-Wc++17-extensions]
return (v || ...);
Run Code Online (Sandbox Code Playgroud)
这在某种程度上表明我正在写的东西在c ++ 17之前还不行,但是编译成功了,并且代码似乎在做应该做的事情。我期望编译会失败。
关于为什么编译器接受我的折叠表达式的任何解释?
我有以下代码(用于演示目的)应该声明所有参数使用C++ 17折叠表达式求值为true.
#include <cassert>
template<typename... Ts>
void fn(Ts... ts)
{
assert(ts && ...);
}
int main()
{
fn(true, true, true);
fn(true, true, false, true);
}
Run Code Online (Sandbox Code Playgroud)
在Coliru,它按预期工作; 它不在我的机器上.我收到了错误
In file included from /usr/include/c++/8.2.1/cassert:44,
from foldexpr.cpp:1:
foldexpr.cpp: In function ‘void fn(Ts ...)’:
foldexpr.cpp:6:15: error: expected ‘)’ before ‘&&’ token
assert(ts && ...);
^~
foldexpr.cpp:6:5: error: expected ‘;’ before ‘)’ token
assert(ts && ...);
^~~~~~
Run Code Online (Sandbox Code Playgroud)
与gcc版本8.2.1 20180831.在Ubuntu与gcc版本5.4.0 20160609我得到
In file included from /usr/include/c++/5/cassert:43:0,
from foldexpr.cpp:1:
foldexpr.cpp: In function ‘void fn(Ts ...)’:
foldexpr.cpp:6:18: error: …Run Code Online (Sandbox Code Playgroud) clang++ ×10
c++ ×7
g++ ×6
c++11 ×3
c++14 ×2
c++17 ×2
ld ×2
clang ×1
constexpr ×1
llvm-clang ×1
macos ×1
makefile ×1
optimization ×1
qt-creator ×1
reference ×1
visual-c++ ×1