c++, short, simple, elegant, solutions. O(n * m) time, O(n * m) space.
Simply create a tempary email from each input email. Modifying as follows; 1. Strip out any . before either either a + or @ is encountered. 2. Exclude anything 
Simply create a tempary email from each input email. Modifying as follows;
1. Strip out any `.` before either either a `+` or `@` is encountered.
2. Exclude anything from `+` to `@` (if a `+` is encounted.

Add the resulting tempary email to a hashset before finally returning the size of the hashset.

### Fast, single pass. O(n * m) time, O(n * m) space where n is number of emails and m is average string length.
```cpp
  int numUniqueEmails(vector<string>& emails) {
    std::unordered_set<std::string> trimmed_emails;
    for (auto& email : emails) {
      std::string tmp;

      // Copy everything that is not a '.' until a '+' or a '@' is encountered			
      auto it = email.begin();
      for (; '@' != *it && '+' != *it; ++it) {
        if ('.' != *it) {
          tmp += *it;
        }
      }

      // Copy the domain into our tempary email
      it = std::find(it, email.end(), '@');
      tmp.append(it, email.end());

      // Add the trimmed email to our set of emails
      trimmed_emails.insert(tmp);
    }
    return trimmed_emails.size();
  }
```	

### A pure stl solution. O(n * m) time, O(n * m) space
```cpp
  int numUniqueEmails(vector<string>& emails) {
    std::unordered_set<std::string> trimmed_emails;
    for (auto& email : emails) {
      std::string tmp;

      // Find the end of the local name
      auto it = std::find_if(email.begin(), email.end(), [](char c) -> bool { return '+' == c || '@' == c; });

      // Copy the local name, excluding any '.'
      std::copy_if(email.begin(), it, std::back_inserter(tmp), [](char c) -> bool { return c != '.';});

      // Add the domain
      it = std::find(it, email.end(), '@');
      std::copy(it, email.end(), std::back_inserter(tmp));

      trimmed_emails.insert(tmp);
    }
    return trimmed_emails.size();
  }
```

### Using `std::string` operations rather than stl algorithms. O(n * m^2) time, O(n * m) space
The copy from the input email upto either `+` or `@`, then loop around removing `.`. This is quadratic, O(m^2) operation because each removal of a '.' requires shifting the remaining string.
```cpp
  int numUniqueEmails(vector<string>& emails) {
    std::unordered_set<std::string> trimmed_emails;
    for (auto& email : emails) {
      auto at_pos = email.find('@');
      auto end_pos = email.find('+');
      if (end_pos == std::string::npos) {
        end_pos = at_pos;
      }
     
      // Copy the local name component
      std::string tmp = email.substr(0, end_pos);
    
      // Quadratically remove '.' from our tempary string
      auto dot_pos = tmp.find('.'); 
      while (dot_pos != std::string::npos) {
        tmp.erase(dot_pos, 1);
        dot_pos = tmp.find('.', dot_pos);
      }
     
      // Add the domain
      tmp += email.substr(at_pos);
      
      trimmed_emails.insert(tmp);
    }
    return trimmed_emails.size();
  }
```

### Faster string operations solutions. O(n * m) time, O(n * m) space.
The quadratic removal of `.`s can be removed by copying the sections between `.`s from the input strings.
```cpp
  int numUniqueEmails(vector<string>& emails) {
    std::unordered_set<std::string> trimmed_emails;
    for (auto& email : emails) {
      auto at_pos = email.find('@');
      auto end_pos = email.find('+');
      if (end_pos == std::string::npos) {
        end_pos = at_pos;
      }
  
      std::string tmp;

      // Copy sections of the input email between the '.'s
      std::string::size_type start = 0;
      auto dot_pos = email.find('.');
      while (dot_pos != std::string::npos && dot_pos < end_pos) {
        tmp += email.substr(start, dot_pos - start);
        start = dot_pos + 1;
        dot_pos = email.find('.', start);
      }
      tmp += email.substr(start, end_pos - start);
     
      // Add the domain
      tmp += email.substr(at_pos);
      
      trimmed_emails.insert(tmp);
    }
    return trimmed_emails.size();
  }
```

I personally prefer the first solution because it copies the input email as it searches and results in a lot less double handling. I frankly hate the `std::string` operations as they tend to be less efficent, but have added them as suggested in the comments.
[]