代码之家  ›  专栏  ›  技术社区  ›  ereOn

奇怪的编译器错误和模板继承

  •  5
  • ereOn  · 技术社区  · 15 年前

    有人能解释一下为什么这个代码:

    class safe_bool_base
    { //13
        protected:
    
            typedef void (safe_bool_base::*bool_type)() const;
    
            void this_type_does_not_support_comparisons() const {} //18
    
            safe_bool_base() {}
            safe_bool_base(const safe_bool_base&) {}
            safe_bool_base& operator=(const safe_bool_base&) { return *this; }
            ~safe_bool_base() {}
    };
    
    template <typename T=void> class safe_bool : public safe_bool_base
    {
        public:
    
            operator bool_type() const
            {
                return (static_cast<const T*>(this))->boolean_test() ? &safe_bool_base::this_type_does_not_support_comparisons : 0;
            }
    
        protected:
    
            ~safe_bool() {}
    };
    
    template <> class safe_bool<void> : public safe_bool_base
    {
        public:
    
            operator bool_type() const
            {
                return (boolean_test() == true) ? &safe_bool_base::this_type_does_not_support_comparisons : 0; //46
            }
    
        protected:
    
            virtual bool boolean_test() const = 0;
            virtual ~safe_bool() {}
    };
    

    c:\project\include\safe_bool.hpp(46) : error C2248: 'safe_bool_base::this_type_does_not_support_comparisons' : cannot access protected member declared in class 'safe_bool_base'
    c:\project\include\safe_bool.hpp(18) : see declaration of 'safe_bool_base::this_type_does_not_support_comparisons'
    c:\project\include\safe_bool.hpp(13) : see declaration of 'safe_bool_base'
    

    因为两者 safe_bool safe_bool_base

    我错过什么了吗?

    3 回复  |  直到 15 年前
        1
  •  9
  •   Chubsdad    15 年前

    这可能会有所帮助(在非模板情况下也可以复制)

    struct A{
    protected:
        void f(){}
    };
    
    struct B : A{
        void g(){&A::f;}        // error, due to Standard rule quoted below
    };
    
    int main(){
    }
    

    VS给出“'A::f”:无法访问 类中声明的受保护成员 “A”

    对于相同的代码,Comeau给出

    受保护函数“A::f”(在 第3)行是 无法通过“a”指针或对象void g(){&a::f;}访问 ^

    “ComeauTest.c”,第7行:警告: 表达式无效 g(){&A::f;}

    struct A{
    protected:
        void f(){}
    };
    
    struct B : A{
        void g(){&B::f;}        // works now
    };
    
    int main(){
    }
    

    那么,为什么第一个代码段不起作用呢?

    11.5/1-“当派生类的友元或成员函数引用 一个受保护的非静态成员函数 或受保护的非静态数据成员 在第11.102条)中,除非形成 指向成员(5.3.1)的指针 对事物的引用或对象 派生类本身(或任何类 访问将形成指向 成员,嵌套的名称说明符 从该类派生的类)。

    因此,在操作符函数中改变return,如下所示

    return (boolean_test() == true) ? &safe_bool<void>::this_type_does_not_support_comparisons : 0; //46 
    
    return (static_cast<const T*>(this))->boolean_test() ? &typename safe_bool<T>::this_type_does_not_support_comparisons : 0; 
    

    编辑2:请忽略我的解释。大卫是对的。这就是它的本质。

    struct A{
    protected:
        int x;
    };
    
    struct B : A{
        void f();
    };
    
    struct C : B{};
    
    struct D: A{            // not from 'C'
    };
    
    void B::f(){
        x = 2;         // it's own 'A' subobjects 'x'. Well-formed
    
        B b;
        b.x = 2;       // access through B, well-formed
    
        C c;
        c.x = 2;       // access in 'B' using 'C' which is derived from 'B', well-formed.
    
        D d;
        d.x = 2;       // ill-formed. 'B' and 'D' unrelated even though 'A' is a common base
    }
    
    int main(){} 
    
        2
  •  1
  •   Oliver Charlesworth    15 年前

    我不认为这与模板有关。您的示例代码可以简化为这样,但仍然会给出等效的错误:

    class A
    {
        protected:
            typedef void (A::*type)() const;
            void foo() const {}
    };
    
    
    class B : public A
    {
        public:
            operator type() const
            {
                return &A::foo;
            }
    };
    

    我认为问题是你不能返回成员函数指针到公共接口中受保护的成员。 ( )

        3
  •  0
  •   aeh    15 年前

    下面是C++标准规则

    14.7.2/11
    实例化
    . [注:特别是函数中使用的模板参数和名称
    声明符(包括参数类型、返回类型和异常规范)可以是
    通常不可访问的私有类型或对象,模板可能是
    通常无法访问的成员模板或成员函数。[尾注]

    解释了为什么泛型模板实例化不会抛出错误。即使您有私有访问说明符,它也不会抛出。

    推荐文章