std::piecewise_construct在<utility>中定义,因为它已声明,因此具有内部链接constexpr.我想知道std::piecewise_construct在标题中使用是否会违反ODR.例如:
#include <utility>
#include <tuple>
struct point
{
point(int x, int y)
: x(x), y(y)
{}
int x, y;
};
inline std::pair<point, point> f(int x1, int y1, int x2, int y2)
{
return {
std::piecewise_construct,
std::forward_as_tuple(x1, y1), std::forward_as_tuple(x2, y2)
};
}
Run Code Online (Sandbox Code Playgroud)
#include "a.hpp"
Run Code Online (Sandbox Code Playgroud)
#include "a.hpp"
Run Code Online (Sandbox Code Playgroud)
TU 1中的std::piecewise_constructin表示f与TU 2中的对象不同f.我怀疑f违反了ODR.
N3290(也可能是ISO/IEC 14882:2011)表示以下情况是ODR的例外,在3.2/5中:
如果对象在D的所有定义中具有相同的文字类型,并且该对象使用常量表达式(5.19)初始化,并且值(但不是地址),则名称可以引用具有内部链接或无链接的const对象使用该对象,并且该对象在D的所有定义中具有相同的值;
f满足几乎所有要求,但"使用对象的值(但不是地址)"对我来说似乎很模糊.确实std::piecewise_construct_t没有状态,但是对分段构造函数的std::pair调用涉及调用隐式声明的复制构造函数std::piecewise_construct_t,其参数是const std::piecewise_construct_t &.地址是"用过的",不是吗?
我很困惑. …
我想知道是否有可能在编译时检查两种类型是否相同.我想出的是(idk如果它有效,因为它感觉hackish和IDK标准好,所以IDK在测试时要寻找什么).
#include <boost/strong_typedef.hpp>
BOOST_STRONG_TYPEDEF(double, cm);
BOOST_STRONG_TYPEDEF(double, inch);
template<typename T, typename U>
static constexpr void __help()
{
}
template<typename T, typename U>
class AreSameType
{
public:
constexpr operator bool()
{
return &__help<T,U> == &__help<U,T>;
};
};
Run Code Online (Sandbox Code Playgroud)
用法:
int main()
{
static_assert(AreSameType<double,float>()== false, "oh noes1");
static_assert(AreSameType<double,double>()== true, "oh noes2");
static_assert(AreSameType<int*,double*>()== false, "oh noes3");
static_assert(AreSameType<double*,double>()== false, "oh noes4");
static_assert(AreSameType<const double,double>()== false, "oh noes5");
static_assert(AreSameType<inch,cm>()== true, "oh expected"); //fires
}
Run Code Online (Sandbox Code Playgroud)
所以
1)有更好的方法吗?
2)这个功能黑客的地址保证按标准工作(我打赌不会:))?
[C++14: 7.1.5/1]:的constexpr说明符将只应用于一个变量或变量模板,功能或功能模板的声明,或文字类型(3.9)的静态数据成员的声明中的定义.如果函数,函数模板或变量模板的任何声明都有一个constexpr说明符,那么它的所有声明都应该包含说明constexpr符.[..]
请注意,第二句没有像第一句话那样提及"静态数据成员",因此本段中没有要求数据成员的所有声明(此处我正在考虑具体的定义声明)constexpr static具有constexpr符.
我也无法在其他地方找到规则.
那么,为什么海湾合作委员会会拒绝以下计划呢?
#include <chrono>
using namespace std::chrono_literals;
#define DUR 1000ms
struct T
{
static constexpr auto dur_1 = DUR;
};
decltype(T::dur_1) T::dur_1;
// main.cpp:12:23: error: 'constexpr' needed for in-class initialization of static data member 'const std::chrono::duration<long int, std::ratio<1l, 1000l> T::dur_1' of non-integral type [-fpermissive]
// decltype(T::dur_1) T::dur_1;
// ^
Run Code Online (Sandbox Code Playgroud) 在程序执行之前,编译器如何知道平方根在内存中的位置?我认为每次执行程序时地址都会不同,但这样做有效:
constexpr double(*fp)(double) = &sqrt;
cout << fp(5.0);
Run Code Online (Sandbox Code Playgroud)
是因为地址是相对于内存中的另一个地址吗?我不这么认为,因为它的值fp很大:0x720E1B94.
请考虑以下代码段:
template <bool> struct B { };
template <typename T>
constexpr bool pred(T t) { return true; }
template <typename T>
auto f(T t) -> decltype(B<pred(t)>{})
{
}
Run Code Online (Sandbox Code Playgroud)
clang ++ (trunk)编译代码
g ++ (trunk)编译失败,出现以下错误:
src:7:34: error: template argument 1 is invalid
auto f(T t) -> decltype(B<pred(t)>{})
^
src:7:34: error: template argument 1 is invalid
src:7:34: error: template argument 1 is invalid
src:7:34: error: template argument 1 is invalid
src:7:34: error: template argument 1 is invalid
src:7:34: error: template …Run Code Online (Sandbox Code Playgroud)Clang接受以下代码,但gcc 拒绝它。
void h() { }
constexpr int f() {
return 1;
h();
}
int main() {
constexpr int i = f();
}
Run Code Online (Sandbox Code Playgroud)
这是错误消息:
g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In function 'constexpr int f()':
main.cpp:5:6: error: call to non-'constexpr' function 'void h()'
h();
~^~
main.cpp: In function 'int main()':
main.cpp:9:24: error: 'constexpr int f()' called in a constant expression
constexpr int i = f();
~^~
main.cpp:9:19: warning: unused variable 'i' [-Wunused-variable]
constexpr int i …Run Code Online (Sandbox Code Playgroud) 我正在测试用户定义的文字.我想让_fac返回数字的阶乘.
让它调用一个constexpr函数是有效的,但它不允许我用模板做,因为编译器抱怨参数不是也不可能constexpr.
我对此感到困惑 - 不是文字常量表达式吗?该5中5_fac始终是一个文字,可以在编译时计算,所以为什么我不能用它作为这样?
第一种方法:
constexpr int factorial_function(int x) {
return (x > 0) ? x * factorial_function(x - 1) : 1;
}
constexpr int operator "" _fac(unsigned long long x) {
return factorial_function(x); // this works
}
Run Code Online (Sandbox Code Playgroud)
第二种方法:
template <int N> struct factorial_template {
static const unsigned int value = N * factorial_template<N - 1>::value;
};
template <> struct factorial_template<0> {
static const unsigned int value = 1; …Run Code Online (Sandbox Code Playgroud) 有时候只需要一个语句(返回时就必须这样)是方便的,甚至是必要的constexpr.如果需要检查条件并且只允许一个语句,则条件运算符是唯一的选项.如果出现错误,最好从条件运算符中抛出异常,例如:
template <typename It>
typename std::iterator_traits<It>::reference
access(It it, It end) {
return it == end? throw std::runtime_error("no element"): *it;
}
Run Code Online (Sandbox Code Playgroud)
但是,当用作例如(实例)时,上述函数不会编译:
std::vector<int> v;
access(v.begin(), v.end());
Run Code Online (Sandbox Code Playgroud)
编译器抱怨尝试将非const引用绑定到临时.不过,编译器并没有抱怨throw-expression本身.所以问题是:可以从条件运算符抛出异常,如果是这样,上面的代码出了什么问题?
可以在运行时创建C-Strings还是std::string必须创建constexpr它们?
使用gcc 4.9.2我可以这样做:
constexpr const char foo[] = "blee";
Run Code Online (Sandbox Code Playgroud)
(遗憾的是,2013年11月的客户技术预览版不允许Visual Studio支持此功能:https://stackoverflow.com/a/29255013/2642059)
但即使使用gcc 4.9.2我也不能这样做:
constexpr const std::string foo = "blee";
Run Code Online (Sandbox Code Playgroud)
我收到错误:
error: the type 'const string {aka const std::basic_string<char>}' of constexpr variable 'foo'
is not literal
constexpr const std::string foo = "blee";
^
note: 'std::basic_string<char>' is not literal because:
class basic_string
^
note: 'std::basic_string<char>' has a non-trivial destructor
Run Code Online (Sandbox Code Playgroud)
但我想更多地澄清为什么 a std::string不是文字.也就是说:为什么必须在运行时构造字符串?
正如所指出的,这个问题可以部分回答:是否可以在constexpr中使用std :: string?但它没有涉及为什么std::string不能成为问题核心的文字.
我试图在C ++类中实现constexpr成员函数,该函数返回模板参数。该代码应该与c ++ 11兼容。但是,当模板化的类还包含STL容器作为数据成员(如std :: vector)时,会遇到编译问题(constexpr成员函数未涉及)。
以下代码给出了一个最小的示例:
#include <vector>
#include <iostream>
#include <array>
template<size_t n>
struct A
{
constexpr size_t dimensions() const
{
return n;
}
private:
std::vector<double> a;
};
int main(int argc,char ** argv)
{
auto a=A<3>();
std::array<double,a.dimensions()> arr;
}
Run Code Online (Sandbox Code Playgroud)
该代码可以使用命令正确编译
g ++ -std = c ++ 14 -O3 quickTest.cpp -o test -Wall
clang ++ -std = c ++ 11 -O3 quickTest.cpp -o test -Wall
但是当我使用失败
g ++ -std = c ++ 11 -O3 quickTest.cpp -o test -Wall
与错误 …