我尝试使用模板特化实现编译时算法选择.
我哈希以下代码:
template <class C>
struct choose
{
typedef size_t (*type)(const C*);
static constexpr type value = java_string_hashcode<C>;
};
Run Code Online (Sandbox Code Playgroud)
我将这种结构专门用于char类型:
template <>
struct choose<char>
{
typedef size_t (*type)(const char*);
static constexpr type value = fnv_1a_32_hash;
};
Run Code Online (Sandbox Code Playgroud)
但是当我尝试编译它时,我得到GCC 4.7.1的以下错误:
错误:字段初始值设定项不是常量
我认为问题来自于fnv_1a_32_hash函数重载的事实,即使IMO隐式转换size_t (*)(const char*)应该处理这个问题.
我终于找到了一个解决方法,通过重命名重载或简单地转换赋值:
static constexpr type value = (type)fnv_1a_32_hash;
Run Code Online (Sandbox Code Playgroud)
我的问题是:这是一个编译器错误吗?或者我错过了什么?请在需要时解释并引用规格.
fnv_1a_32_hash实施细节:
constexpr size_t fnv_1a_32_hash(const char* p, size_t h) noexcept
{
return (*p == 0) ? h : fnv_1a_32_hash(p + 1, (h ^ *p) …Run Code Online (Sandbox Code Playgroud) 我们来看一个这个简单的例子:
#include <iostream>
namespace foo {
constexpr int main(int argc, char* argv[]) {
// code
}
}
int main(int argc, char* argv[])
{
return foo::main(argc, argv);
}
Run Code Online (Sandbox Code Playgroud)
取决于代码是什么,clang会抱怨或不抱怨.如果代码是:
cout << "Hello!";
return 0;
Run Code Online (Sandbox Code Playgroud)
clang抱怨:
错误:constexpr函数永远不会产生常量表达式[-Winvalid-constexpr]
Run Code Online (Sandbox Code Playgroud)constexpr int main(int argc, char* argv[]) {注意:非constexpr函数'operator <<>'不能用于常量表达式
Run Code Online (Sandbox Code Playgroud)std::cout << "Hello!";/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/ostream:530:5:注意:在这里声明
Run Code Online (Sandbox Code Playgroud)operator<<(basic_ostream<char, _Traits>& __out, const char* __s)
很公平,constexpr函数不能包含任何cout语句,我们知道.但是如果我们这样做会发生什么?
for (int i = 0; i < argc; i++)
std::cout << argv[i];
Run Code Online (Sandbox Code Playgroud)
clang允许它!好吧,但这不可能是一个constexpr函数,即使它被标记为constexpr,让我们尝试在constexpr上下文中使用它.
int arr[foo::main(argc, argv)];
Run Code Online (Sandbox Code Playgroud)
有用!那一定是clang bug?我之所以说clang是因为gcc抱怨:
错误:constexpr函数的主体'constexpr int foo :: main(int,char**)'不是return语句 …
请原谅我的长篇文章,但我不能让这个程序工作,除非我指定-fpermissivegcc而不是在clang下.你能帮我解决这个例子吗?
namespace detail
{
template<typename T>
constexpr auto address(T&& t) ->
typename ::std::remove_reference<T>::type*
{
return &t;
}
template <typename FP, FP fp, class C, typename ...A>
struct S
{
static constexpr auto* l = false ? address(
[](C* const object) noexcept
{
return [object](A&& ...args) {
return (object->*fp)(::std::forward<A>(args)...);
};
}) :
nullptr
;
};
template <typename FP, FP fp, typename R, class C, typename ...A>
auto make_member_delegate(C* const object, R (C::* const)(A...)) ->
decltype((*S<FP, fp, C, A...>::l)(object))
{ …Run Code Online (Sandbox Code Playgroud) 考虑以下代码
struct S
{
constexpr S() = default;
constexpr S(S const &) = default;
constexpr S(S &) = default;
constexpr S(S &&) = default;
#if 1
S & operator = (S const &) = default;
S & operator = (S &) = default;
S & operator = (S &&) = default;
#else
constexpr S & operator = (S const &) = default;
constexpr S & operator = (S &) = default;
constexpr S & operator = (S &&) = default; …Run Code Online (Sandbox Code Playgroud) 在实现 std::experimental::optional(cppreference.com)时,我对特定构造函数的规范感到困惑,即:
constexpr optional( const T& value ); // (4)
Run Code Online (Sandbox Code Playgroud)
(来源)
optional<T>对于易于破坏的类型T,该构造函数允许在constexpr上下文中构造.虽然第一个要求,即在这种情况下关闭用户提供的析构函数来制作optional<T>文字类型,直接解决,我不知道如何绕过constexpr中不允许的放置限制.
我认为我应该实现optional<T>使用std::aligned_storage<T>以允许T不是默认构造的类型并满足任何对齐要求(如果适用).但正如我所说,constexpr禁止我在特定构造函数中使用placement new.
我喝咖啡多少,而且我没有看到明显的解决方案吗?
谢谢
我正在玩constexprC++ 14及以上版本的构造函数,并注意到一些奇怪的东西.这是我的代码:
#include <iostream>
#include <string>
using std::cout;
using std::endl;
#define PFN(x) cout << x << __PRETTY_FUNCTION__ << endl
#define PF PFN("")
#define NL cout << endl
struct A {
constexpr A() { PF; }
virtual ~A() { PF; NL; }
};
struct B : A {
constexpr B() { PFN(" "); }
virtual ~B() { PFN(" "); }
};
int main(int argc, char** argv) {
{ A a; }
{ B b; }
A* a = new …Run Code Online (Sandbox Code Playgroud) 以下代码可以使用clang ++ 3.8.0和g ++ 7.2.0 成功编译(编译标记为):-std=c++14 -Wall -Wextra -Werror -pedantic-errors
struct Foo
{
constexpr operator bool() const
{
return false;
}
};
int main()
{
constexpr bool b = Foo{};
(void)b;
}
Run Code Online (Sandbox Code Playgroud)
编译器的这种行为是否符合标准?请注意,将任何成员(如int i;)添加到Foo类都不会改变任何内容。
如果我初始化constexpr变量foo在一个翻译单元,其具有非缺省值,然后一个初始化另一个constexpr变量bar与foo在另一翻译单元有可能是bar之前被初始化foo导致bar,是由初始化为零或缺省初始化foo。即与在非constexpr情况下(静态初始化顺序彻底失败有效)不同,编译器和链接器是否将分析依赖性顺序以确保正确的结果?
另外,constexpr变量模板如何受到影响?在单个翻译单元中,它们的初始化顺序是不确定的。
首选C ++ 17标准答案。
更新:这是一个最小的示例。有用; 那就是问题所在。至此,我99%确信这可以通过静态初始化命令惨败(TSIOF)来解决。但是,由于该问题的极端,阴险性质,我需要确认这是可以的。我相信该代码不会受到TSIOF的困扰,因为在xh命令a和bx.cc转换单元中包含了yh 。但是,AFAIU有2个翻译单元:一个包含a,另一个包含b。此外,AFAI-sort-of-U对a错误的多重定义不会出现,因为static关键字具有内部链接,但a仍然具有全局范围。
编译为:
clang++ -std=c++17 x.cc y.cc #or g++
Run Code Online (Sandbox Code Playgroud)
可能的输出:
in foo
Run Code Online (Sandbox Code Playgroud)
可能的输出:
assertion failed (core dumped)
Run Code Online (Sandbox Code Playgroud)
文件x.cc:
#include "x.h"
int main(){ assert(b == 42); foo(); }
Run Code Online (Sandbox Code Playgroud)
文件xh:
#pragma once
#include "y.h"
static constexpr int b = a+1;
Run Code Online (Sandbox Code Playgroud)
文件y.cc:
#include …Run Code Online (Sandbox Code Playgroud) 在constexpr:Introduction中,发言者提到"编译时浮点计算可能与运行时计算的结果不同":

原因与"交叉编译"有关.
老实说,我无法清楚地理解这个想法.恕我直言,不同的平台也可能有不同的整数实现.
为什么它只影响浮点数?或者我想念什么?
c++ floating-point floating-accuracy language-lawyer constexpr
我想知道为什么std::launder是一个constexpr功能.是否有任何用例可以在编译时使用?