如果可以为编译器做的话,我正在寻找一种在编译时检查函数参数的方法.
更具体一点:假设我们有一些类Matrix.
class Matrix
{
int x_size;
int y_size;
public:
Matrix(int width, int height):
x_size{width},
y_size{height}
{}
Matrix():
Matrix(0, 0)
{}
};
int main()
{
Matrix a; // good.
Matrix b(1, 10); // good.
Matrix c(0, 4); // bad, I want compilation error here.
}
Run Code Online (Sandbox Code Playgroud)
那么,在传递给函数的静态(源编码)值的情况下,我可以检查或区分行为(函数重载?)?
如果值不是静态的:
std::cin >> size;
Matrix d(size, size);
Run Code Online (Sandbox Code Playgroud)
我们只能做运行时检查.但是如果值在源代码中编码?在这种情况下我可以进行编译时检查吗?
编辑:我认为这可以通过constexpr构造函数实现,但无论如何都不允许使用和不使用constexpr进行重载.所以问题无法以我想象的方式解决.
我正准备通过std::tuple
在包括单个元素在内的很多情况下使用来使我的代码更加通用化.我的意思是例如tuple<double>
而不是double
.但我决定检查这个特例的表现.
这是简单的性能基准测试:
#include <tuple>
#include <iostream>
using std::cout;
using std::endl;
using std::get;
using std::tuple;
int main(void)
{
#ifdef TUPLE
using double_t = std::tuple<double>;
#else
using double_t = double;
#endif
constexpr int count = 1e9;
auto array = new double_t[count];
long long sum = 0;
for (int idx = 0; idx < count; ++idx) {
#ifdef TUPLE
sum += get<0>(array[idx]);
#else
sum += array[idx];
#endif
}
delete[] array;
cout << sum << endl; // just …
Run Code Online (Sandbox Code Playgroud) 我想基于模板参数值选择成员函数(复制构造函数)的实现.我想有两种方法:SFINAE和模板部分特化.
最后一个应该是这样的:
#include <iostream>
template<typename A, bool sw>
struct B
{
B() {}
B(const B &b);
};
template<typename A>
B<A, false>::B(const B<A, false> &b)
{
std::cout << "false\n";
}
template<typename A>
B<A, true>::B(const B<A, true> &b)
{
std::cout << "true\n";
}
int main()
{
}
Run Code Online (Sandbox Code Playgroud)
它没有编译:nested name specifier 'B<A, false>::' for declaration does not refer into a class, class template or class template partial specialization
.
SFINAE方法也失败了:
#include <type_traits>
#include <iostream>
template<typename A, bool sw>
struct B
{
B() …
Run Code Online (Sandbox Code Playgroud) 我发现代码的奇怪行为显然忽略了const-ness:
#include <iostream>
using std::cerr;
class A
{
public:
A() { cerr << "A::A()\n"; }
A(const A &a) { cerr << "A::A(const A&)\n"; }
A(A &&) { cerr << "A::A(A&&)\n"; }
A & operator = (const A &a) { cerr << "A::operator=(const A&)\n"; return *this; }
A & operator = (A &&a) { cerr << "A::operator(A&&)\n"; return *this; }
~A() { cerr << "A::~A()\n"; }
const A get() const { cerr << "const A A::get() const\n"; return A(); }
A …
Run Code Online (Sandbox Code Playgroud) 我正在编写程序的一部分,它解析并验证程序控制台参数中的一些用户输入.我选择使用stringstream用于此目的,但遇到无符号类型读取的问题.
下一个模板用于从给定字符串中读取请求的类型:
#include <iostream>
#include <sstream>
#include <string>
using std::string;
using std::stringstream;
using std::cout;
using std::endl;
template<typename ValueType>
ValueType read_value(string s)
{
stringstream ss(s);
ValueType res;
ss >> res;
if (ss.fail() or not ss.eof())
throw string("Bad argument: ") + s;
return res;
}
// +template specializations for strings, etc.
int main(void)
{
cout << read_value<unsigned int>("-10") << endl;
}
Run Code Online (Sandbox Code Playgroud)
如果类型是无符号的,输入字符串包含负数,我希望看到异常抛出(由引起ss.fail() = true
).但是stringstream会生成转换为无符号类型的值(书面示例中为4294967286).
如何修复此样本以实现所需的行为(最好不回退到c函数)?我知道它可以通过简单的第一个符号检查完成,但我可以放置前导空格.我可以编写自己的解析器,但不相信问题是如此不可预测,标准库无法解决它.
对于无符号类型,隐藏在stringstream运算符深处的函数是strtoull和strtoul.它们以描述的方式工作,但提到的功能是低级的.为什么stringstream不提供一些验证级别?(我只是希望我错了,但确实需要一些动作来实现这一点).
我正在用cmake编写构建配置:除了带有自己代码的主项目外,还有一些外部库.为了方便更新这些库(zlib,libpng,...),我不想修改其cmakelists文件,但我需要特定的库目标(例如在target_link_libraries()中使用).另一个限制是,我不能只说我的代码需要安装外部库,所有东西必须位于一个源代码树中,并且必须一起构建.为了保持所有库提供结构化(库,标题),我想将make install
库(如同)安装到本地构建文件夹,然后包含生成的cmake文件以将所需目标导入到我的项目中.
我想流程如下:
add_subdirectory()
问题是自动执行第2步(需要在主项目CMakeLists.txt内触发install
目标add_subdiretory
).我可以构建和安装所有库,然后构建自己的代码,但这不方便.
所以问题是如何告诉cmake在构建期间进行中间安装?
这里有一个小例子:
文件结构:
prj/CMakeLists.txt
prj/src/main.cpp
lib/CMakeLists.txt
lib/include/libheader.h
lib/src/libsource.cpp
Run Code Online (Sandbox Code Playgroud)
PRJ /的CMakeLists.txt
project(TestProject)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_VERBOSE_MAKEFILE on)
set(WORK_DIR ${CMAKE_CURRENT_SOURCE_DIR})
# supposed to use add_subdirectory here (with forced install).
# and then include prespecified include-file as here.
include_directories(${WORK_DIR}/../lib/build/install/include)
include(${WORK_DIR}/../lib/build/install/lib/libtargets.cmake)
add_executable(main ${WORK_DIR}/src/main.cpp)
target_link_libraries(main library_target)
Run Code Online (Sandbox Code Playgroud)
LIB /的CMakeLists.txt
project(TestLib)
cmake_minimum_required(VERSION 2.8)
set(CMAKE_VERBOSE_MAKEFILE on)
set(WORK_DIR ${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${WORK_DIR}/include)
add_library(library_target STATIC ${WORK_DIR}/src/libsource.cpp)
set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/install)
install(FILES ${WORK_DIR}/include/libheader.h DESTINATION include)
install(TARGETS library_target DESTINATION lib EXPORT libtargets) …
Run Code Online (Sandbox Code Playgroud) 我最近已从默认的binutils链接程序ld.bfd切换到ld.gold(以使链接时间优化工作正常,为什么不这样做?)。它是手工制作的(例如:http://wiki.gentoo.org/wiki/Gold)。结果,我得到了从/ usr / bin / ld到ld.gold二进制文件的符号链接链,因此在构建过程中透明更改了链接器。
但是,当我尝试重建所有软件包时,我发现ld.gold有时会导致配置/编译失败,例如“ C编译器无法创建可执行文件”:
checking for x86_64-pc-linux-gnu-gcc... x86_64-pc-linux-gnu-gcc
checking whether the C compiler works... no
configure: error: in `/var/tmp/portage/sys-libs/db-6.0.30-r1/work/db-6.0.30/build_unix-abi_x86_64.amd64':
configure: error: C compiler cannot create executables
Run Code Online (Sandbox Code Playgroud)
哪个实际上是链接器问题:
configure: checking whether the C compiler works
/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.4/../../../../x86_64-pc-linux-gnu/bin/ld: --default-symver: unknown option
/usr/lib/gcc/x86_64-pc-linux-gnu/4.8.4/../../../../x86_64-pc-linux-gnu/bin/ld: use the --help option for usage information
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
但是可以使用默认的bfd链接器成功构建软件包,因此问题是对于不能使用ld.gold构建的软件包,如何返回bfd链接器?
问题软件包为= sys-libs / db-6.0.30-r1(目前引起我注意的软件包)。
是否可以将赋值运算符推导为成员函数模板的特例?
例如,我有一个带有一个bool参数的类模板,并且想要实现assign操作,而不管模板参数的任何特定值.
#include <iostream>
template<bool sw>
struct A {
A() {
std::cout << __PRETTY_FUNCTION__ << '\n';
}
template<bool input_sw>
A & operator = (const A<input_sw> &a) {
std::cout << __PRETTY_FUNCTION__ << '\n';
return *this;
}
};
int main()
{
A<true> a;
A<true> b;
a = b;
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码片段中,clang和gcc编译的二进制文件不打印任何关于赋值 - 据我所知,默认赋值在这里生成,尽管可以从模板中推导出它.