Home > Blockchain >  Why does my compiler complain about a missing template argument for a concept?
Why does my compiler complain about a missing template argument for a concept?

Time:08-02

Initially I had following concept which worked just fine:

template<typename T,  typename...KEYS>
concept js_concept = requires(T t, int index, std::string& json_body, KEYS... keys, std::string key) {
    { t.template get_value<T>(keys) } -> std::same_as<T>;
    { t.template get_value<T>(key) } -> std::same_as<T>;
};

The two above is just to have a distinction between 1/several args.

Now I would simply implement this by:

class JsoncppImpl {

  template<typename T, typename... KEYS>
  T get_value(KEYS&& ... keys) {
    /// impl
  } 
  template<typename T>
  T get_value(std::string key) {
    /// impl
  } 
}

And the use case:

class JsonUtil {
public:
    template<js_concept JSON_OPERATOR>
    JsonUtil(std::string body, JSON_OPERATOR&& json_impl){
        m_st = json_impl.get_value<std::string>(body);

    }
  std::string m_st;
};

int main( ){
    std::string body = "c  ";
    JsonUtil<JsoncppImpl::value> jsoncpp(body, JsoncppImpl{});
    return 0;
}

That works just fine. If I do the following addition by adding another function to the concept returning a template argument:

 template<typename T , typename VALUE, typename...KEYS>
concept js_concept = requires(T t, int index, std::string& json_body, KEYS... keys, std::string key) { //
    // setting consts  here is  pointless (these are  treated as  pr values)
    { t.template get_value<T>(keys) } -> std::same_as<T>;
    { t.template get_value<T>(key) } -> std::same_as<T>;
    { t.template release() } -> std::same_as<VALUE>;

};

and adding the additional function to the implemention:

JsoncppImpl::release(){ return std::move(m_some_internal_value);}

The variable ´m_some_internal_value´ is just some type well defined within JsoncppImpl. It can even be defined as a primitive type.

Now using the release function:

     template<js_concept JSON_OPERATOR>
    JsonUtil::JsonUtil(std::string body, JSON_OPERATOR&& json_impl){
        m_st = json_impl.get_value<std::string>(body);
        auto val = json_impl.release();

    }

Gives following compiler error:

js_concept' requires more than 1 template argument; provide the remaining arguments explicitly to use it here
    template<js_concept JSON_OPERATOR>

CodePudding user response:

template<js_concept JSON_OPERATOR>
JsonUtil(std::string body, JSON_OPERATOR&& json_impl) {}

Is equivalent to

template<typename JSON_OPERATOR>
JsonUtil(std::string body, JSON_OPERATOR&& json_impl)
requires js_concept<JSON_OPERATOR> {}

KEYS... empty, so it works fine. (But I really doubt if it behaves as you expect...

When you add another template parameter, you have to explicitly provide it since the compiler has no idea where it comes from.

You could do like this,

template<typename VALUE, js_concept<VALUE> JSON_OPERATOR>
JsonUtil::JsonUtil(std::string body, JSON_OPERATOR&& json_impl){
  • Related