Euler problem c++ / std::library usage
Your conversions are... pretty WTF :)

void insert_if_product(string const&amp; factor1, string const&amp; factor2, string const&amp; product) {
    auto p = std::stoul(product);
    if (std::stoul(factor1, nullptr, 10) * std::stoul(factor2, nullptr, 10) == p) {
        products.insert(p);
    }
}


I mean why use an intermediate stream? Why, if you're using a stream, build it using string concatenation? Also, why pass in copies of read-only strings?!
avoid unnecesary allocations:

string factor1 = perm.substr(0, 1);
string factor2 = perm.substr(1, 3);
string product = perm.substr(4, 5);


is gonna do a lot of allocations. Probably more than you'd think. At least, reuse factor1,factor2 and product capacities? (My sample below makes them static)


  Edit Squeezing a few more drops out:

avoiding strings in more places avoids the temps from perm.substr(). Now I just directly assign by indices:

    factor1.assign(perm.begin()+0, perm.begin()+1);
    factor2.assign(perm.begin()+1, perm.begin()+4);
    product.assign(perm.begin()+4, perm.begin()+9);

using unordered_set seems to shave off milliseconds on average :)


Quick performance comparison (g++ -std=c++11 -march=native -O3`) shows the time taken goes down from ~1.036s to ~0.116s.

So, roughly 8.9x speed effectively.

Full code:

#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;unordered_set&gt;
#include &lt;algorithm&gt;
#include &lt;numeric&gt;
#include &lt;sstream&gt;

// store the products, a set is ideal because of the HINT:
std::unordered_set&lt;unsigned&gt; products;

/**
 * Insert to products if string arguments is a proper product
 */
void insert_if_product(std::string const&amp; factor1, std::string const&amp; factor2, std::string const&amp; product) {
    auto p = std::stoul(product);
    if (std::stoul(factor1, nullptr, 10) * std::stoul(factor2, nullptr, 10) == p) {
        products.insert(p);
    }
}

/**
 * magnitudes needs to add up: I'm checking 
 * 9 digits total
 * m1 * m3 = m5
 * m1 * m4 = m4
 * m2 * m3 = m4
 * Is this all?
 * 
 * @param check this permutation
 */

void check_products(std::string const&amp; perm)
{
    static std::string factor1, factor2, product;
    // all permutations are coming from perm, so no need to perm stuff here.
    factor1.assign(perm.begin()+0, perm.begin()+1);
    factor2.assign(perm.begin()+1, perm.begin()+4);
    product.assign(perm.begin()+4, perm.begin()+9);

    insert_if_product(factor1, factor2, product);

//  factor1.assign(perm.begin()+0, perm.begin()+1);
    factor2.assign(perm.begin()+1, perm.begin()+5);
    product.assign(perm.begin()+5, perm.begin()+9);

    insert_if_product(factor1, factor2, product);

    factor1.assign(perm.begin()+0, perm.begin()+2);
    factor2.assign(perm.begin()+2, perm.begin()+5);
//  product.assign(perm.begin()+5, perm.begin()+9);

    insert_if_product(factor1, factor2, product);
}

int main() {
    std::string s = "123456789";

    do {
        check_products(s);
    } while(std::next_permutation(std::begin(s), std::end(s)));

    std::cout &lt;&lt; "Sum:" &lt;&lt; std::accumulate(products.begin(), products.end(), 0u) &lt;&lt; "\n";
}