C++ 模板结构 'has no member named' 错误
C++ template struct 'has no member named' error
当 T==B
等 T==A
时,我可以在不对无成员 a 发出警告的情况下进行编译的唯一方法是在 if 语句块中 reinterpret_cast
和通过指针访问非共享成员。有没有办法解决这个问题或以其他方式提示编译器?
这是 gcc 4。8.x
enum Type { A, B};
template<Type T> struct S { };
template<> struct S<A> { int x; int a; };
template<> struct S<B> { int y; int x; int b; };
template<Type T> static void foo(int x)
{
// lots of code
S<T> s;
s.x = someCall();
if (T == A)
{
s.a = 1;
}
else if (T == B)
{
s.y = 2;
s.b = 3;
}
// a bunch of common code
}
编辑:我知道制作一个专门的特定函数来处理细节,但我希望避免额外的样板代码。
您可以使用专业化:
template <Type T> void bar(S<T>&);
template <> void bar(S<A>& s) {s.a = 1;}
template <> void bar(S<B>& s) {s.y = 2; s.b = 3;}
template<Type T> static void foo(int x)
{
// lots of code
S<T> s;
s.x = someCall();
bar(s);
// a bunch of common code
}
if (T == A)
[...]
else if (T == B)
[...]
A
、B
和 T
这里是编译时实体,而不是 运行 时实体。然而,您正试图对编译时已知的事物执行 运行 时间评估。现在可以肯定的是,您可以尝试用一种不确定的转换(尝试,然后失败)来破解某些东西,或者尝试一些其他类型的笨拙,但代码告诉您:您做错了。
专业化 foo
是一种方式,利用 SFINAE 可能也是如此(与 enable_if
一样),但从我在这里看到的你的用例来看,这也是错误的做法.那是因为您要实现的代码是某种初始化代码,或者是操纵正在使用的对象的内部状态的代码。从某种意义上说,你违反了单一责任原则。
因此将该代码移至责任所属的位置:在 class 中 init
ed。
template<> struct S<A> { int x; int a; void init() {a=1;} };
template<> struct S<B> { int y; int x; int b; void init() { x=2; y=3; } };
template<Type T> static void foo(int x)
{
// lots of code
S<T> s;
s.x = someCall();
s.init();
// a bunch of common code
}
您也可以使用工厂 class。这将抽象掉对象的实例化和对 init()
的调用,后者可以根据最终类型采用不同的参数。
当 T==B
等 T==A
时,我可以在不对无成员 a 发出警告的情况下进行编译的唯一方法是在 if 语句块中 reinterpret_cast
和通过指针访问非共享成员。有没有办法解决这个问题或以其他方式提示编译器?
这是 gcc 4。8.x
enum Type { A, B};
template<Type T> struct S { };
template<> struct S<A> { int x; int a; };
template<> struct S<B> { int y; int x; int b; };
template<Type T> static void foo(int x)
{
// lots of code
S<T> s;
s.x = someCall();
if (T == A)
{
s.a = 1;
}
else if (T == B)
{
s.y = 2;
s.b = 3;
}
// a bunch of common code
}
编辑:我知道制作一个专门的特定函数来处理细节,但我希望避免额外的样板代码。
您可以使用专业化:
template <Type T> void bar(S<T>&);
template <> void bar(S<A>& s) {s.a = 1;}
template <> void bar(S<B>& s) {s.y = 2; s.b = 3;}
template<Type T> static void foo(int x)
{
// lots of code
S<T> s;
s.x = someCall();
bar(s);
// a bunch of common code
}
if (T == A)
[...]
else if (T == B)
[...]
A
、B
和 T
这里是编译时实体,而不是 运行 时实体。然而,您正试图对编译时已知的事物执行 运行 时间评估。现在可以肯定的是,您可以尝试用一种不确定的转换(尝试,然后失败)来破解某些东西,或者尝试一些其他类型的笨拙,但代码告诉您:您做错了。
专业化 foo
是一种方式,利用 SFINAE 可能也是如此(与 enable_if
一样),但从我在这里看到的你的用例来看,这也是错误的做法.那是因为您要实现的代码是某种初始化代码,或者是操纵正在使用的对象的内部状态的代码。从某种意义上说,你违反了单一责任原则。
因此将该代码移至责任所属的位置:在 class 中 init
ed。
template<> struct S<A> { int x; int a; void init() {a=1;} };
template<> struct S<B> { int y; int x; int b; void init() { x=2; y=3; } };
template<Type T> static void foo(int x)
{
// lots of code
S<T> s;
s.x = someCall();
s.init();
// a bunch of common code
}
您也可以使用工厂 class。这将抽象掉对象的实例化和对 init()
的调用,后者可以根据最终类型采用不同的参数。