gpt4 book ai didi

C++ GCC 为什么这段 sfinae 代码可以用 GCC 4.7 编译,但不能用 4.8 编译?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:31:50 28 4
gpt4 key购买 nike

我喜欢在模板类中使用本地类来执行类似“static if”的构造。但是我遇到了 gcc 4.8 不想编译我的代码的问题。但是 4.7 可以。

这个例子:

#include <type_traits>
#include <iostream>
#include <string>

using namespace std;

struct A {
void printA() {
cout << "I am A" << endl;
}
};
struct B {
void printB() {
cout << "I am B" << endl;
}
};

template <typename T>
struct Test {
void print() {
struct IfA {
constexpr IfA(T &value) : value(value) {
}
T &value;
void print() {
value.printA();
}
};
struct IfB {
constexpr IfB(T &value) : value(value) {
}
T &value;
void print() {
value.printB();
}
};
struct Else {
constexpr Else(...) {}
void print() {
}
};
typename conditional<is_same<T, A>::value, IfA, Else>::type(value).print();
typename conditional<is_same<T, B>::value, IfB, Else>::type(value).print();
}
T value;
};

int main() {
Test<A>().print();
Test<B>().print();
}

选项:

g++ --std=c++11 main.cc -o local-sfinae

任务:

  1. 给定具有不同打印接口(interface)的类 A 和 B。
  2. 编写一个可以同时打印 A 和 B 的通用类测试。
  3. 不要污染任何命名空间或类范围。

代码说明:

  1. 这只是一个干净的例子。
  2. 我使用这样的方法,因为我想概括“static if”的构造。看,我通过字段将参数传递给 IfA 和 IfB 类,而不是直接传递给 print() 函数。
  3. 我经常使用这样的结构。
  4. 我发现这些构造不应该在(污染)类范围内。我的意思是它们应该放在方法范围内。

所以问题。

这段代码不能用 GCC 4.8 编译。因为它会检查所有类,即使它们从未被使用过。但它没有以二进制形式实例化它们(我已经注释掉导致错误的行并使用 gcc 4.8 编译它)。证明:

$ nm local-sfinae |c++filt |grep "::If.*print"
0000000000400724 W Test<A>::print()::IfA::print()
00000000004007fe W Test<B>::print()::IfB::print()

看,没有 Test::print()::IfB::print()。 (稍后见:'void Test::print()::IfB::print() [with T = A]')

如果我用 gcc 4.8 编译上述代码的错误:

g++ --std=c++11 main.cc -o local-sfinae
main.cc: In instantiation of 'void Test<T>::print()::IfB::print() [with T = A]':
main.cc:36:9: required from 'void Test<T>::print() [with T = A]'
main.cc:49:21: required from here
main.cc:34:17: error: 'struct A' has no member named 'printB'
value.printB();
^
main.cc: In instantiation of 'void Test<T>::print()::IfA::print() [with T = B]':
main.cc:28:9: required from 'void Test<T>::print() [with T = B]'
main.cc:50:21: required from here
main.cc:26:17: error: 'struct B' has no member named 'printA'
value.printA();
^
  1. 这是 GCC 4.8 的错误吗?
  2. 还是 GCC 4.7 的错误?也许代码不应该被编译。
  3. 或者这是我的错误,我不应该依赖编译器行为/不应该使用这种方法来实现“静态 if”。

附加信息:

这个简单的代码可以在 4.7 上编译,但不能在 4.8 上编译。我把它缩短了。

struct A {
void exist() {
}
};

template <typename T>
struct Test {
void print() {
struct LocalClass {
constexpr LocalClass(T &value) : value(value) {
}
T &value;
void print() {
value.notExist();
}
};
}
T value;
};

int main() {
Test<A>().print();
}

错误:

main.cc: In instantiation of 'void Test<T>::print()::LocalClass::print() [with T = A]':
main.cc:16:9: required from 'void Test<T>::print() [with T = A]'
main.cc:22:21: required from here
main.cc:14:17: error: 'struct A' has no member named 'notExist'
value.notExist();
^

测试了两个 GCC 4.8 版本:2012.10 和 2013.02。希望这是 GCC 4.8 的错误并且可以修复。

最佳答案

LocalClass 不是模板。 “未使用则不实例化”规则仅适用于类模板的成员函数。

也就是说,当 Test::print() 被实例化时,里面的所有东西都会被激活,包括其本地类中未使用的成员。

关于C++ GCC 为什么这段 sfinae 代码可以用 GCC 4.7 编译,但不能用 4.8 编译?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15457338/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com