Home > Net >  Universal reference deduction using the same_as concept
Universal reference deduction using the same_as concept

Time:09-15

I'm trying to implement a push function for a blocking queue which accepts a universal reference as it's template parameter, but requires that the template argument be the same type as the queue's element type:

template <typename ValueType>
class shared_queue
{
public:
    template <typename Arg>
        requires std::same_as<Arg, ValueType>
    void push(Arg&& arg);
private:
    std::deque<ValueType> container_;
};

However, I'm not quite sure how is universal reference deduction supposed to work in this case, or if it works at all for that matter. The following code:

shared_queue<int> sq;
int x{ 5 };
sq.push(x); // won't compile
sq.push(5); // all good

does not compile. The compiler complains that: Compiler error, constraints not satisfied

I'm pretty sure I'm misunderstanding something but I don't know what.

CodePudding user response:

You need to remove_reference from Arg for same_as to consider the int& to x and int the same type. You may also want to remove const in case you have const int x and pass that as a parameter. Removing both ( volatile) can be done with std::remove_cvref_t:

template <typename Arg>
    requires std::same_as<std::remove_cvref_t<Arg>, ValueType>
void push(Arg&& arg) {
    container_.push_back(std::forward<Arg>(arg));
}

Another option would be to allow for any arguments that can be used to construct a ValueType:

template <class... Args>
    requires std::constructible_from<ValueType, Args...>
void emplace(Args&&... args) {
    container_.emplace(container_.end(), std::forward<Args>(args)...);
}
  • Related