emplace enables you to avoid copying or moving the value you are about to insert and, instead, it constructs it in-place with the
arguments provided.
Prefer using emplace, or emplace_hint if all the conditions hold:
  -  You are inserting a single value. 
-  You are constructing a fresh temporary value just to insert it into the set. 
-  You expect that the key is not in the set. 
You should keep the insert in any of the cases below:
  -  You are inserting multiple values in one shot. 
-  You are inserting a pre-existing value that is constructed for another purpose. 
-  You are inserting an object that is cheap to move or to copy (e.g., an integer). 
-  The key you are inserting is likely to be in the set (in this case by using insertyou avoid creating a useless temporary node).
This rule detects calls to insert that lead to the creation of a large temporary object that can be avoided by using the
emplace member function.
Noncompliant code example
struct A {
  int x;
  std::array<std::string, 100> more;// Expensive to copy or move
public:
  A(int x, const std::string& more) : x(x), more({more}) {}
  bool operator<(A const &other) const {
    return x < other.x;
  }
};
std::array<std::string, 3> strs = {"big brown fox", "little kitten", "regular human"};
void f() {
  std::set<A> set;
  for (int i = 0; i < 1'000'000; ++i) {
    set.insert(A{i, strs[i%3]});// Noncompliant
  }
}
Compliant solution
struct A {
  int x;
  std::array<std::string, 100> more;// Expensive to copy or move
public:
  A(int x, const std::string& more) : x(x), more({more}) {}
  bool operator<(A const &other) const {
    return x < other.x;
  }
};
std::array<std::string, 3> strs = {"big brown fox", "little kitten", "regular human"};
void f() {
  std::set<A> set;
  for (int i = 0; i < 1'000'000; ++i) {
    set.emplace(i, strs[i%3]);// Compliant
  }
}
Exceptions
You should keep insert for exception safety if your key type is a smart pointer and the argument is a new expression.