标签: constexpr

std :: piecewise_construct不会导致ODR违规吗?

std::piecewise_construct在<utility>中定义,因为它已声明,因此具有内部链接constexpr.我想知道std::piecewise_construct在标题中使用是否会违反ODR.例如:

a.hpp

#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)

翻译单位1

#include "a.hpp"
Run Code Online (Sandbox Code Playgroud)

翻译单位2

#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 &.地址是"用过的",不是吗?

我很困惑. …

c++ one-definition-rule linkage constexpr c++11

24
推荐指数
1
解决办法
632
查看次数

如何在编译时检查两种类型是否相同(如果它与Boost强类型定义一起使用,则为奖励积分)

我想知道是否有可能在编译时检查两种类型是否相同.我想出的是(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++ static-assert template-meta-programming constexpr c++11

24
推荐指数
1
解决办法
1万
查看次数

为什么GCC认为constexpr静态数据成员的定义必须标记为constexpr?

[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)

c++ gcc constexpr c++14

24
推荐指数
1
解决办法
1378
查看次数

为什么函数指针可以是`constexpr`?

在程序执行之前,编译器如何知道平方根在内存中的位置?我认为每次执行程序时地址都会不同,但这样做有效:

constexpr double(*fp)(double) = &sqrt;
cout << fp(5.0);
Run Code Online (Sandbox Code Playgroud)

是因为地址是相对于内存中的另一个地址吗?我不这么认为,因为它的值fp很大:0x720E1B94.

c++ function-pointers constexpr

24
推荐指数
4
解决办法
2540
查看次数

使用函数参数作为常量表达式的一部分 - gcc vs clang

请考虑以下代码段:

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)

c++ language-lawyer constant-expression constexpr c++11

24
推荐指数
1
解决办法
478
查看次数

下面的代码是格式错误的NDR还是格式正确的?

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)

c++ language-lawyer constexpr c++17

24
推荐指数
1
解决办法
852
查看次数

用户定义的文字参数不是constexpr?

我正在测试用户定义的文字.我想让_fac返回数字的阶乘.

让它调用一个constexpr函数是有效的,但它不允许我用模板做,因为编译器抱怨参数不是也不可能constexpr.

我对此感到困惑 - 不是文字常量表达式吗?该55_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)

c++ user-defined-literals constexpr c++11

23
推荐指数
2
解决办法
3908
查看次数

可以从三元运算符抛出异常吗?

有时候只需要一个语句(返回时就必须这样)是方便的,甚至是必要的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++ constexpr c++11

23
推荐指数
3
解决办法
1456
查看次数

为什么必须在运行时构造字符串?

可以在运行时创建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++ literals stdstring constexpr c++11

23
推荐指数
2
解决办法
2092
查看次数

C ++中具有std :: vector数据成员的constexpr成员函数

我试图在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

与错误 …

c++ constexpr c++11

23
推荐指数
1
解决办法
764
查看次数