Function chaining is great when used for a Fluent syntax. For example, the following code is highly readable and functional:
sqlFactory.select("*")
.from("some_table")
.where("somevalue = 12")
.execute();
In C++, libraries like cpplinq achieve similar results with syntax such as:
cpplinq::from(some_collection)
>> cpplinq::where([](auto data) { return data.value == expected; })
>> cpplinq::select([](auto data) { return data.other_value == expected; })
>> cpplinq::to_vector();
Such syntax is both readable and greatly extensible. In these situation the chaining is inherent to the design pattern and, increases readability. It's intuitive and useful. However, as others have pointed out setters do not logically return a value so should not, it's simply not a returned value one would intuitively expect.