What happens with you code is the following:
s is of type std::set<int> and therefore is suitable for storing variables of type int.
Calling the function std::set<int>::insert expects an argument of type int. If you do s.insert((1, 3)) you actually don't insert a pair but use the comma-operator. It works like this: In an expression a, b, expression a is evaluated, then expression b is evaluated and the result of expression b is returned as the result of the whole expression. You can read more about it here: How does the Comma Operator work.
Therefore s.insert((1, 3)) results in s.insert(3) and 3 is inserted into s.
To achieve the desired behaviour you can use std::pair, defined in the header utility. A possible way could be the following:
std::set<std::pair<int, int>> s;
s.insert(std::make_pair(1, 1));
s.insert(std::make_pair(1, 3));
s.insert(std::make_pair(3, 1));
s.insert(std::make_pair(3, 3));
for (const auto& e : s)
std::cout << "(" << e.first << ", " << e.second << ") ";
Output:
(1, 1) (1, 3) (3, 1) (3, 3)
An additional syntax to insert the pairs is the following using initializer lists:
s.insert({1, 3});
If you want to construct the pairs in place instead of constructing and inserting them, you can use std::set::emplace as follows:
s.emplace(1, 3);