0

I have 3 classes, Device, Register, and WriteOnlyPolicy, defined as such:

Device

class Device
{
public:

    template<class Register>
    inline void write(typename Register::value_type value)
    {
        Register::writeRegister(value, this);
    }

protected:

    // limit device-specific API calls to this function
    virtual void writeDeviceRegister(uint64_t address, uint64_t value) = 0;

};

Register

template<uint64_t ADDRESS, class ValueType, template<class> class AccessPolicy>
struct Register : public AccessPolicy<ValueType>
{
    using value_type = ValueType;
    using access_policy = AccessPolicy<ValueType>;

    static void writeRegister(value_type value, Device* device)
    {
        access_policy::write(ADDRESS, device, value);
    }
}

WriteOnlyPolicy

template<typename value_type>
class WriteOnlyPolicy
{
protected:

    static void write(uint64_t ADDRESS, Device* device, value_type value)
    {
        // convert from a value_type to a uint64_t...
        // Shift/mask as needed...
        device->writeDeviceRegister(ADDRESS, value);
    }
};

Register and WriteOnlyPolicy never actually get instantiated in this scheme, but I want the policy to call the protected writeDeviceRegister function of the Device class. I don't want that function to be public as I only want to expose the write function to users of the class, and not the device-specific implementation.

In order to allow that I want Device to friend Register::access_policy (which in this case would be the WriteOnlyPolicy class given as a template argument), but I can't figure out the syntax to friend a dependent typename of a template class. Is this possible?

I thought that putting a friend declaration in the Device class such as

template<uint64_t a, class b, template<class> class c>
friend typename Register<a,b,c>::access_policy;

would do the trick, but I get the error

error: expected unqualified-id before ';' token

Nicolas Holthaus
  • 7,763
  • 4
  • 42
  • 97
  • You cannot friend a particular member function of a class (template or not) selectively. I'm gonna search the dupe now. – πάντα ῥεῖ Aug 17 '16 at 17:08
  • @πάνταῥεῖ just to be clear I'm trying to friend the member typedef (which is a class) not the member function. – Nicolas Holthaus Aug 17 '16 at 17:09
  • 1
    show your attempts. – Karoly Horvath Aug 17 '16 at 17:16
  • Unfortunately you didn't leave a [MCVE] that demonstrates your problem actually, you probably need to refer that type using the `typename` keyword in front. – πάντα ῥεῖ Aug 17 '16 at 17:17
  • See here for some more info: http://stackoverflow.com/questions/610245/where-and-why-do-i-have-to-put-the-template-and-typename-keywords – πάντα ῥεῖ Aug 17 '16 at 17:19
  • @πάνταῥεῖ @KarolyHorvath I updated the question with my attempted `friend` declaration and the subsequent error. – Nicolas Holthaus Aug 17 '16 at 17:22
  • 3
    You cannot do this. You can make the `Register` class template a friend, and call a private function of `Register` from within the policy (passing its type to the policy, and befriending the policy). Alternatively, you can change the call to `Register` into `Register::writeRegister(value, this, &Device::writeDeviceRegister);`, which may pass this member function pointer along to the policy, which can then call it on the `Derive` pointer (or pass a lambda.. it's all template code anyway..). – Johannes Schaub - litb Aug 17 '16 at 17:24
  • @JohannesSchaub-litb thanks, I was wondering if it wasn't allowed. I think passing the function is probably cleaner than friendship in either case. – Nicolas Holthaus Aug 17 '16 at 17:28

0 Answers0