大小为“N”的两个向量的标量积定义为 SP(a, b) = a_1 * b_1 + ... + a_N * b_N。
编译时整数向量定义为:
template<int... I>
struct Vector;
Run Code Online (Sandbox Code Playgroud)
功能产品界面:
template<typename Vector1, typename Vector2>
constexpr int product
Run Code Online (Sandbox Code Playgroud)
例如,可以使用以下代码进行测试:
static_assert(product<Vector<1, 2, 5>, Vector<1, 3, 4>> == 27);
Run Code Online (Sandbox Code Playgroud)
如何实现产品才能匹配上面的断言和接口?
我无法在cpprefference上找到与成员值匹配的概念的正确语法static constexpr。此代码可以在 GCC 和 MSVC 上编译并正常运行,但在 Clang 中不起作用。我想知道是否有人知道这是我的错误,还是 GCC 和 MSVC 或 Clang 的问题?这是所有三个编译器都打开的Godbolt,我认为它说明了这一点!
#include <concepts>
#include <iostream>
template<typename T>
concept MyConcept = requires (T t){
requires t.member == 1;
//[clang's error]
// note: because 't.member == 1' would be invalid:
// constraint variable 't' cannot be used in an evaluated context
};
struct S {
constexpr static int member {2};
};
struct D {
constexpr static int member {1};
};
template<MyConcept …Run Code Online (Sandbox Code Playgroud) 如果有一个模板 constexpr 变量(例如用于计算斐波那契数列)并且想要为某些模板参数实例化它,则constexpr在实例化期间必须重复关键字吗?
template<int N> constexpr size_t fib = fib<N-1> + fib<N-2>;
template<> constexpr size_t fib<1> = 1;
template<> constexpr size_t fib<2> = 1;
//template constexpr size_t fib<70>; // GCC error
template size_t fib<70>; // Clang error
Run Code Online (Sandbox Code Playgroud)
这里的问题是 GCC 坚持删除关键字:
error: explicit instantiation shall not use 'constexpr' specifier
Run Code Online (Sandbox Code Playgroud)
而 Clang 坚持保留它:
error: type 'size_t' (aka 'unsigned long') of explicit instantiation of 'fib' does not match expected type 'const size_t' (aka 'const unsigned long')
Run Code Online (Sandbox Code Playgroud)
演示: https: //gcc.godbolt.org/z/f6rMjz95E
根据标准,哪个编译器是正确的?
我有这样的代码:
template<typename ... Args>
constexpr size_t get_init_size(Args ... args) {
return sizeof...(Args);
}
template<typename ... Args>
constexpr auto make_generic_header(Args ... args) {
constexpr size_t header_lenght = get_init_size(args...);
return header_lenght;
}
constexpr auto create_ipv4_header() {
constexpr auto x = make_generic_header(0b01, 0b10, 0b01);
return x;
}
Run Code Online (Sandbox Code Playgroud)
我知道这是虚拟代码,但我将其隔离以查找错误。
编译器给我错误(GCC):
In instantiation of 'constexpr auto make_generic_header(Args&& ...) [with Args = {int, int, int}]':
/tmp/tmp.CaO5YHcqd8/network.h:39:43: required from here
/tmp/tmp.CaO5YHcqd8/network.h:31:22: error: 'args#0' is not a constant expression
31 | constexpr size_t header_lenght = get_init_size(args...);
| ^~~~~~~~~~~~~ …Run Code Online (Sandbox Code Playgroud) constexpr我想为一个类提供Color如下功能:
// color.hpp
struct Color
{
Color(int r, int g, int b, int a);
static const Color Red;
// ...
};
// color.cpp
Color::Color(int r, int g, int b, int a) { /* ... */ }
const Color Color::Red(255, 0, 0, 255);
// ...
Run Code Online (Sandbox Code Playgroud)
我的愿望是保持此类的 API 不变,因此我想完全删除color.cpp并对头文件进行以下更改:
// color.hpp
struct Color
{
constexpr Color(int r, int g, int b, int a) { /* ... */ }
inline static constexpr Color Red{255, 0, 0, 255};
// …Run Code Online (Sandbox Code Playgroud) 如果类没有任何 constexpr 构造函数,是否有任何理由将 constexpr 添加到类的方法中?也许编译器在这种情况下可以做一些优化?
我想在编译时生成各种位掩码:
0x11111111或者0x1111111111111111
0xF0F0F0F0或者0xF0F0F0F0F0F0F0F0
大小取决于类型,是 32 位还是 64 位。
前任:
template <typename T> genMask(unsigned char templt) {
....
};
genMask<uint32_t>(0xF0);
genMask<uint64_t>(0xF0);
Run Code Online (Sandbox Code Playgroud)
第一次调用应该生成0xF0F0F0F0,而第二次调用 genMask 应该生成0xF0F0F0F0F0F0F0F0
目前我已经对这些进行了硬编码。
这里的任何想法将不胜感激。
编辑:这是一种老式的做法:
#define MASK(b) ((T(-1) / 0xFF) * (b))
其中 T 是类型。
鉴于我想改进我的 C++ 代码库。第一步是将函数标记为constexpr满足所用 C++ 标准的要求。有没有办法判断一个函数是否可以被标记constexpr?
我想出的唯一方法是添加constexpr到单个实例,运行编译器,并检查它是否抱怨它不是constexpr。重复直到检查完所有实例。这种方法无法扩展。
我试图弄清楚哪种是在变量类型列表上实现函数的最惯用的方式.例如,计算所有类型的最大大小.我知道有几种方法可以完成这样的任务,但我想知道何时选择哪种策略.
这些是我会考虑的机制(可能存在更多,如果是这样,请提及):
输入特征(理想情况下使用声明):
template <typename Head>
using max_size = typename std::integral_constant<size_t, sizeof(Head)>::type;
template <typename Head, typename... Tail>
using max_size = ?;
Run Code Online (Sandbox Code Playgroud)constexpr 功能:
template <typename Head>
constexpr size_t max_size() { return sizeof(Head); }
template <typename Head, typename... Tail>
constexpr size_t max_size() { ? }
Run Code Online (Sandbox Code Playgroud)我的问题是双重的:
计算的哪些特征决定了选择什么策略?
在每种情况下,上述最大尺寸示例的示例实现如何?
请考虑以下代码:
struct foo {
int bar(int, int = 0) {
return 0;
}
};
constexpr auto ptr = &foo::bar;
int main() {
return (foo{}.*ptr)(0);
}
Run Code Online (Sandbox Code Playgroud)
正如所料,此代码无法使用最新版本的GCC,Clang和MSVC进行编译.
但是,假设的编译器能够通过constexpr成员函数指针传递默认参数是合理的.如果这个编译器成功编译了<edit>上面的代码而没有警告</ edit>,有效地传递0, 0给foo::bar它,它是否仍然符合ISO C++标准?
可接受的答案将参考标准(或其工作草案).我还没有在N4567的工作草案中找到答案.
编辑:如果标准没有对此问题发表评论,我也会接受这个问题.
c++ ×10
constexpr ×10
c++11 ×2
c++17 ×2
templates ×2
c++-concepts ×1
c++20 ×1
class ×1
compile-time ×1
optimization ×1
static ×1