Question

I have a template function:

template <typename T>
inline void Acquire_Store(volatile T* ptr, T value) {
  // ...
}

When I try to invoke it like this:

volatile Node* node;
Acquire_Store(&node, static_cast<Node*>(nullptr));

The both g++, clang++ compilers say something like this:

deduced conflicting types for parameter 'T' ('volatile List::Node *' vs. 'List::Node *')

What is a correct way to invoke this template function?

Update.

Now I'm not sure about node's type - maybe, I should change it to Node* volatile node;?

I want the variable node to be volatile, but not the pointed object.

Was it helpful?

Solution

The substitution and deduction is not lexically like with a macro. volatile T* will not become volatile Node** but volatile Node* volatile*. The second volatile comes from the template. That makes T equal volatile Node* for the first parameter.

Try to free yourself from sticking the volatile always at the beginning, but put it qhere it belongs according to the actual type. A volatile pointer has the volatile after the star, not before it.

OTHER TIPS

compiler actually you told about your problem clearly enough: you can't have T be different types at the same time (of instantiation). that is because you cast the second parameter incorrectly. for example you may "fix" it like this:

// kate: hl C++11;
#include <iostream>

struct Node {};

template <typename T>
inline void Acquire_Store(volatile T* ptr, T value)
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}

int main()
{
    volatile Node* node;
    Acquire_Store(&node, static_cast<volatile Node*>(nullptr));
    return 0;
}

then output will be

void Acquire_Store(volatile T*, T) [with T = volatile Node*]

but I still don't understand what are you trying to achieve...

It appears the problem is that the volatile qualifier is binding to whatever type T is.

template <typename T>
inline void Acquire_Store(volatile T* ptr, T value)

So when T = Node * for the above, it is the pointer to Node that is volatile and not the Node itself. To make the pointed to object volatile qualified it has to be part of T. This presents a problem because your second parameter is non-volatile -- T cannot both be volatile and non-volatile at the same time.

What you can do is make T = volatile Node * and then remove that volatile qualifier from the second argument using type_traits:

template <typename T>
inline void Acquire_Store(T *ptr, typename std::remove_volatile<T>::type value);

Note all this applies to const qualifier as well. Ideone demos this for const qualifier.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top