C ++模板struct'没有名为'的成员错误

时间:2015-03-10 17:10:50

标签: c++ templates c++11

我可以在没有成员a的情况下编译而不发出警告的唯一方法T==B等等T==Areinterpret_cast在if语句中阻止并访问非指定成员通过指针。有没有办法绕过这个或提示编译器呢?

这是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
}

编辑:我知道如何制作专门的特定功能来处理细节,但我希望避免额外的样板代码。

2 个答案:

答案 0 :(得分:2)

您可以使用专业化:

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
}

答案 1 :(得分:0)

if (T == A)
[...]
else if (T == B)
[...]

ABT这里是编译时实体,而不是运行时实体。然而,您正在尝试对编译时已知的内容执行运行时评估。现在可以肯定的是,你可以试着通过一种不经常的演员(尝试和失败)来破解某些东西,或尝试其他类型的kludgery,但代码告诉你:你做错了。

专业化foo是一种方式,可能是SFINAE(与enable_if一样),但从我在这里看到的用例很少,那也是错误的。这是因为您希望实现的代码是某种初始化代码,或者是操纵正在使用的对象的内部状态的代码。从某种意义上说,你违反了单一责任原则。

所以将代码移到责任所在的位置:在init编辑的类中。

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
}

您也可以使用工厂类。这将抽象出对象的实例化和对init()的调用,它可以根据最终类型采用不同的参数。