我正在使用有关有状态元编程的代码示例。 可以从以下链接找到原始代码示例:http://b.atch.se/posts/non-constant-constant-expressions/#appendix-clang-workaround
为了理解这种技术,我尝试每次修改代码示例。以下是最新版本仍然有效:
Command
对我来说,用int替换Tag似乎微不足道。但实际上,这种替换会产生constexpr int adl_flag(int);
template <class Tag> struct writer {
friend constexpr int adl_flag(int) {
return 0;
}
};
template <int = adl_flag(0)> constexpr bool is_flag_usable(int) {
return true;
}
constexpr bool is_flag_usable (...) {
return false;
}
template <
class Tag = int,
bool B = is_flag_usable(0),
int = sizeof (writer<Tag>) // replace Tag with int
>
constexpr int f() {
return B;
}
int main() {
constexpr int a = f();
constexpr int b = f();
static_assert(a != b, "fail");
return 0;
}
。
我想这是因为编译器不再为第二次调用隐式实例化f:
static_assert fail
但模板类型参数Tag似乎与此无关。请问有人能解释一下这里到底发生了什么。
我使用的编译器是constexpr int b = f();
。使用g++ 5.4.1
进行编译。
答案 0 :(得分:3)
sizeof(writer<int>)
不依赖。这意味着在第一阶段查找中找到wrapper<int>
,解析f
时(一次)。
sizeof(writer<Tag>)
依赖于Tag
。因此,它的查找推迟到第二阶段,当f
被实例化时(在每个呼叫站点)。