>
>These two cases are indistinguishable.

Are they? While we seem to have wandered off the Boost territories, consider this: If B (== typeof(propB)) were defined effectively as

class B {
public: void get(...);
private: void set(...);
friend class A;
};

would that not have the effect desired? Conceptually you could use the CRTP pattern to mix A in to the instantiation of propB so that only A was a friend.

I don't think you can do this in real life with templates because gcc does not allow declaring template parameters as friends
(e.g., this does not compile)

template < typename T > class X { friend T; };


I would suggest using something similar as a "password type". Tested with MSVC 9


#include <boost/type_traits/is_same.hpp>
#include <boost/utility/enable_if.hpp>

#include <iostream>

template<class Type, class PasswordT=void>
class Property
{
   
public:
    Type const& get()const
    {
        return value_;
    }

   

    template<class PwdT>
    void set( Type const& value)
    {
        set_impl<PwdT, PasswordT>(value);
    }

    void set(Type const& value)
    {
        set_impl<void, PasswordT>(value);
    }


private:
    template<class Pwd, class ExpectedPwd>
    void set_impl( Type const& value
                 , typename boost::enable_if<boost::is_same<Pwd, ExpectedPwd> >::type* enable =0
                 )
    {
        value_ = value;
    }



private:
    Type value_;
};


class A
{
private:
    struct secret {};

public:
    Property<int>                test1;
    Property<long, secret>        test2;

    void set_via_a(long l)
    {
        test2.set<secret>(l);
    }
};


int main()
{
    A a;
    a.test1.set(10);
    //a.test2.set(20); //ERROR

    a.set_via_a(20);

    using namespace std;

    cout << "test1: " << a.test1.get()
        << "\ntest2: " << a.test2.get();


    return 0;
}


Hope that helps,
Ovanes