I have a recursive template definition (I just made up that term). I think code explains it better.
template<typename X>
class Domain
{
public:
X begin;
X end;
Domain(
X _begin,
X _end)
: begin(_begin)
, end(_end)
{
// ...
}
bool Contains(
const X& t) const
{
// ...
}
};
template<typename X, typename Y>
class IFunction
{
public:
Domain<X> myDomain;
public:
IFunction(
const Domain<X>& dom)
: myDomain(dom)
{
}
virtual Y
Calc(
const X& IV) const = 0;
virtual IFunction<X, Y>*
GetDerivative() const = 0;
};
template<typename X, typename Y, int n>
class NthOrderFunction
: public IFunction<X, Y>
{
public:
double coeffs[n+1];
public:
NthOrderFunction(
const Domain<X>& dom,
... )
: IFunction(dom)
{
}
virtual Y
Calc(
const X& IV) const
{
// temporary compile solution
return Y();
}
virtual IFunction<X, Y>*
GetDerivative() const
{
if ( n > 1 )
{
return new NthOrderFunction<X, Y, n-1>(dom, ...);
}
return new FlatLine<X, Y>(dom);
}
};
I took out a lot of inheritance and other relations to keep it readable, simple and mysterious. So a new typo might have snuck in while editing the code, but please ignore it. The code has worked fine for years, the only problem I have is the one I'm going to point out.
I recently added a "GetDerivative" function, and it's implementation in the NthOrderFunction class is giving me problems. I know that template classes are defined before compilation but after the preprocessing. As such, I can't see how to bring this functionality ever to work. Every NthOrderFunction with template parameter n, requires a NthOrderFunction with template parameter n-1. You can see that this is a problem. The thing is, even though n will never be negative in use, no amount of coding I do, will convince the "template definition engine" to not bother with instances of n < 1;
has anyone ever had any problems with this? And what solutions did you come up with?
This is the same as the template metaprogramming 101 example- factorial, just the content is somewhat more complex.
template<int N> struct factorial { enum { value = N * factorial<N-1>::value }; };
And you need the same solution- a specialization for the base case.
template<> struct factorial<1> { enum { value = 1 }; };
Yours would be partial rather than full, but it would still work.
Add something like:
template<typename X, typename Y>
class NthOrderFunction<X, Y, 1>
: public IFunction<X, Y>
{
public:
double coeffs[n+1];
public:
NthOrderFunction(
const Domain<X>& dom,
... )
: IFunction(dom)
{
}
virtual Y
Calc(
const X& IV) const
{
// temporary compile solution
return Y();
}
virtual IFunction<X, Y>*
GetDerivative() const
{
return new FlatLine<X, Y>(dom);
}
};
and remove the n==1 case from your recursion case.
As an advice, get some book or tutorial or such on template metaprogramming. One of the base techniques is using recursion in templates in this fashion. This strictly speaking isn't metaprogramming yet, it's just recursive templates. The book/tutorial will explain how more advanced tricks work which you can use to your benefit when expanding on this.
The reason this works is that the original would still expand the compile-time "if" to runtime code (that would just never be executed). This code replaces the one case where it could be compiled out with one where it isn't present, so there's no option for infinite recursion.
Related
I'm trying to understand how to use Concepts to do interface checks on a type (duck typing?), and produce the most readable code. I have the following concept:
template <typename T>
concept Shape = requires(const T& t)
{
{ t.area() } -> std::convertible_to<float>;
};
And then use it as follows
template <typename T>
struct shape_checker_check_in_ctor
{
shape_checker_check_in_ctor()
{static_assert(Shape<T>);}
};
struct Circle : shape_checker_check_in_ctor<Circle>
{
float r;
float area() const
{return 22*r*r/7;}
};
Which works fine, but I think having the static_assert in the constructor of the constraint checker makes its role a tad less obvious. What I'd like instead is the following, which involves less boilerplate:
template <typename T> requires Shape<T>
struct shape_checker_with_constraint
{};
And then
struct Square : shape_checker_with_constraint<Square>
{
double side;
float area() const
{return side*side;}
};
But it doesn't work. Full code here: https://godbolt.org/z/GzEq54P8Y
Can anyone figure out why please?
CRTP is amazing, but doesn't solve every problem. CRTP is not the right tool here.
The test you need to do has to happen after the type is fully defined.
You have hacked it by putting a static assert in the constructor.
Here I simply put the static assert right after the class definition, when it is complete.
struct Circle
{
float r;
float area() const
{return 22*r*r/7;}
};
static_assert( Shape<Circle> );
struct Square
{
double side;
float area() const
{return side*side;}
};
static_assert( Shape<Square> );
now in a future version of C++, we expect to get reflection and eventually (maybe) metaclasses.
With metaclasses, you'd be able to do something like
class(Shape) Circle {
float r;
float area() const
{return 22*r*r/7;}
};
and the metaclass Shape would perform checks and manipulation of the struct. This proposal is in its early steps and won't show up until after we have reflection (which was delayed from c++23 by the pandemic).
I am wondering if there is a way in C++ (especially with C++20) to write some kind of interface for classes/structs.
For example in Java interface is a completely "abstract class" that is used to group related methods with empty bodies:
interface Animal
{
public void animalSound();
public void run();
}
In C++ you could use a pure virtual method declarations to achieve the same behavior.
class Animal
{
public:
virtual void animalSound() = 0;
virtual void run() = 0;
};
But with virtual methods you have runtime costs, and I am not interested in inheritance.
So this runtime cost should not be necessary. I just want compile time checks for my "Animal" classes/structs.
With C++20's Concepts I am sure that it is achievable to build a construct
that you can apply to a class to guarantee that a certain set of methods is provided.
What I was trying to do looked a bit like this.
template<typename Animal_> concept Animal =
requires()
{
(Animal_{}); // default constructable
(Animal_{}.animalSound());
(Animal_{}.run());
};
But I am not sure that this is very c++ish to do.
(By the way is there a way to require the return type of method to be of a specific type?)
And I am not sure how to attach this to a class/struct.
My first thought was to use a static_assert inside the class/struct:
class Cow
{
private: // compile time type checking
static_assert(std::is_matching_concept<Animal, Cow>);
public:
void animalSound() const noexcept {}
void run() const noexcept {}
};
Where std::is_matching_concept is a placeholder for a constraint that I can not find.
I am looking for best practice feedback and suggestions to solve my problem.
EDIT - Add use case
// given the following code
template<typename Vector_, typename Float_=float> concept Vector =
requires()
{
(Vector_{}); // default constructable
(Vector_{}.X())->Float_;
(Vector_{}.Y())->Float_;
};
[[nodiscard]] constexpr auto Pow2(const auto x) noexcept
{
return x * x;
}
[[nodiscard]] constexpr auto LengthPow2(Vector auto vec) noexcept // the use of Vector
{
return Pow2(vec.X()) + Pow2(vec.Y());
}
// Now I want to implement a Vector
// and I want compile time checking, that I have no missed any properties
struct VectorImpl1
{
// EDITED: as #QuentinUK mentioned the static_assert should be in a public scope
// "If in the private part of a class the concepts
// can pass for private members which isn't what you'd want."
public:
// EDITED: as #DavisHerring mentioned this is the way to go
static_assert(Vector<VectorImpl1>);
public:
constexpr VectorImpl1() noexcept = default;
constexpr VectorImpl1(float x, float y) noexcept : x_(x), y_(y) {}
private:
float x_{};
float y_{};
public:
[[nodiscard]] constexpr float X() const noexcept
{ return x_; }
[[nodiscard]] constexpr float Y() const noexcept
{ return y_; }
};
struct VectorImpl2
{
public:
static_assert(Vector<VectorImpl2>);
public:
constexpr VectorImpl2() noexcept = default;
constexpr VectorImpl2(float rad, float length) noexcept : rad_(rad), length_(length) {}
private:
float rad_{};
float length_{};
public:
[[nodiscard]] constexpr float X() const noexcept
{ return CalcX(rad_, length_); }
[[nodiscard]] constexpr float Y() const noexcept
{ return CalcY(rad_, length_); }
};
You can, the question is why you want to do this.
If your type doesn't do what it's suppose to - you'll get a compilation error, right?
If you want to get a compilation error in the same header for some reason, you can do something like:
template <typename ...>
using void_t = void; // available since c++17 in std
template <typename T>
using cow_test = void_t<
decltype(std::declval<T>().moo(0)),
decltype(std::declval<T>().chew(0))
>;
class cow {
public:
void moo(int);
void chew(int);
};
using test_cow = cow_test<cow>;
class cat {
public:
void meaw(int);
void chew(int);
};
using test_cat = cow_test<cat>;
This will fail in test_cat with:
r #1) C++
x86-64 gcc 10.1
Compiler options...
1
<Compilation failed>
x86-64 gcc 10.1 - 364ms
#1 with x86-64 gcc 10.1
<source>: In substitution of 'template<class T> using cow_test = void_t<decltype (declval<T>().moo(0)), decltype (declval<T>().chew(0))> [with T = cat]':
<source>:26:30: required from here
<source>:8:33: error: 'class cat' has no member named 'moo'
8 | decltype(std::declval<T>().moo(0)),
| ~~~~~~~~~~~~~~~~~~^~~
godbolt
I have a suspicion, though, that what you want is to act upon this information: basically - if my class can moo() - moo, otherwise meaw.
This can be achieved, before concepts, by using detection idiom, I suggest watching this: two part talk by Walter Brown or read this blog by Simon Brand
I'm implementing a graph class, with each vertex having a Label of not necessarily the same type. I want the user to be able to provide any Labels (at compile time), without the Graph or the Vertex to know what the type is. For this, I used templated polymorphism, which I've hidden inside a Label class, in order for the Labels to have value semantics. It works like a charm and the relevant code is this (ignore the commented parts for now):
//Label.hpp:
#include <memory>
class Label {
public:
template<class T> Label(const T& name) : m_pName(new Name<T>(name)) {}
Label(const Label& other) : m_pName(other.m_pName->copy()) {}
// Label(const Label& other, size_t extraInfo) : m_pName(other.m_pName->copyAndAddInfo(extraInfo)) {}
bool operator==(const Label& other) const { return *m_pName == *other.m_pName; }
private:
struct NameBase {
public:
virtual ~NameBase() = default;
virtual NameBase* copy() const = 0;
// virtual NameBase* copyAndAddInfo(size_t info) const = 0;
virtual bool operator==(const NameBase& other) const = 0;
};
template<class T> struct Name : NameBase {
public:
Name(T name) : m_name(std::move(name)) {}
NameBase* copy() const override { return new Name<T>(m_name); }
// NameBase* copyAndAddInfo(size_t info) const override {
// return new Name<std::pair<T, size_t>>(std::make_pair(m_name, info));
// }
bool operator==(const NameBase& other) const override {
const auto pOtherCasted = dynamic_cast<const Name<T>*>(&other);
if(pOtherCasted == nullptr) return false;
return m_name == pOtherCasted->m_name;
}
private:
T m_name;
};
std::unique_ptr<NameBase> m_pName;
};
One requirement of the user (aka me) is to be able to create disjoint unions of Graphs (he is already able to create dual Graphs, unions of Graphs (where vertices having the same Label, are mapped to the same vertex), etc.). The wish is that the labels of the new Graph are pairs of the old label and some integer, denoting from which graph the label came (this also ensures that the new labels are all different). For this, I thought that I could use the commented parts of the Label class, but the problem that my g++17 compiler has, is that the moment I define the first Label with some type T, it tries to instantiate everything that could be used:
Name<T>, Name<std::pair<T, size_t>>, Name<std::pair<std::pair<T, size_t>, size_t>>, ...
Try for example to compile this (just an example, that otherwise works):
// testLabel.cpp:
#include "Label.hpp"
#include <vector>
#include <iostream>
int main() {
std::vector<Label> labels;
labels.emplace_back(5);
labels.emplace_back(2.1);
labels.emplace_back(std::make_pair(true, 2));
Label testLabel(std::make_pair(true, 2));
for(const auto& label : labels)
std::cout<<(label == testLabel)<<std::endl;
return 0;
}
The compilation just freezes. (I do not get the message "maximum template recursion capacity exceeded", that I saw others get, but it obviously tries to instantiate everything). I've tried to separate the function in another class and explicitly initialize only the needed templates, in order to trick the compiler, but with no effect.
The desired behaviour (I do not know if possible), is to instantiate the used template classes (together with the member function declarations), but define the member functions lazily, i.e. only if they really get called. For example, if I call Label(3), there should be a class Name<int>, but the function
NameBase* Name<int>::copyAndAddInfo(size_t info) const;
shall only be defined if I call it, at some point. (thus, the Name<std::pair<int, size_t>> is only going to be instantiated on demand)
It feels like something which should be doable, since the compiler already defines templated functions on demand.
An idea whould be to completely change the implementation and use variants, but
I do not want to keep track of the types the user needs manually, and
I quite like this implementation approach and want to see its limits, before changing it.
Does anyone have any hints on how I could solve this problem?
To directly answer your question, the virtual and template combo makes it impossible for the compiler to lazily implement the body copyAndAddInfo. The virtual base type pointer hides the type information, so when the compiler sees other.m_pName->copyAndAddInfo, it couldn't know what type it needs to lazily implement.
EDIT:
Ok, so based on your rationale for using templates, it seems like you only want to accept labels of different types, and might not actually care if the disjoint union information is part of the type. If that's the case, you could move it from the name to the label, and make it run-time information:
class Label {
public:
template<class T> Label(const T& name) : m_pName(new Name<T>(name)) {}
Label(const Label& other) : m_pName(other.m_pName->copy()), m_extraInfo(other.m_extraInfo) { }
Label(const Label& other, size_t extraInfo) : m_pName(other.m_pName->copy()), m_extraInfo(other.m_extraInfo) {
m_extraInfo.push_back(extraInfo);
}
bool operator==(const Label& other) const {
return *m_pName == *other.m_pName && std::equal(
m_extraInfo.begin(), m_extraInfo.end(),
other.m_extraInfo.begin(), other.m_extraInfo.end()); }
private:
struct NameBase { /* same as before */ };
std::vector<size_t> m_extraInfo;
std::unique_ptr<NameBase> m_pName;
};
If the disjoint union info being part of the type is important, than please enjoy my original sarcastic answer below.
ORIGINAL ANSWER:
That said, if you're willing to put a cap on the recursion, I have an evil solution for you that works for up to N levels of nesting: use template tricks to count the level of nesting. Then use SFINAE to throw an error after N levels, instead of recursing forever.
First, to count the levels of nesting:
template <typename T, size_t Level>
struct CountNestedPairsImpl
{
static constexpr size_t value = Level;
};
template <typename T, size_t Level>
struct CountNestedPairsImpl<std::pair<T, size_t>, Level> : CountNestedPairsImpl<T, Level + 1>
{
using CountNestedPairsImpl<T, Level + 1>::value;
};
template <typename T>
using CountNestedPairs = CountNestedPairsImpl<T, 0>;
Then, use std::enable_if<> to generate different bodies based on the nesting level:
constexpr size_t NESTING_LIMIT = 4;
NameBase* copyAndAddInfo(size_t info) const override {
return copyAndAddInfoImpl(info);
}
template <typename U = T, typename std::enable_if<CountNestedPairs<U>::value < NESTING_LIMIT, nullptr_t>::type = nullptr>
NameBase* copyAndAddInfoImpl(size_t info) const {
return new Name<std::pair<T, size_t>>(std::make_pair(m_name, info));
}
template <typename U = T, typename std::enable_if<CountNestedPairs<U>::value >= NESTING_LIMIT, nullptr_t>::type = nullptr>
NameBase* copyAndAddInfoImpl(size_t info) const {
throw std::runtime_error("too much disjoint union nesting");
}
Why did I call this evil? It's going to generate every possible level of nesting allowed, so if you use NESTING_LIMIT=20 it will generate 20 classes per label type. But hey, at least it compiles!
https://godbolt.org/z/eaQTzB
My problem is pretty simple, i want to use lambda's in the same way i may use a functor as a 'comparator', let me explain a little better. I have two big structs, both of them have their own implementation of operator<, and i have also a useless class (this is just the name of the class in the context of this question) which use the two struct, everything looks like this:
struct be_less
{
//A lot of stuff
int val;
be_less(int p_v):val(p_v){}
bool operator<(const be_less& p_other) const
{
return val < p_other.val;
}
};
struct be_more
{
//A lot of stuff
int val;
be_more(int p_v):val(p_v){}
bool operator<(const be_more& p_other) const
{
return val > p_other.val;
}
};
class useless
{
priority_queue<be_less> less_q;
priority_queue<be_more> more_q;
public:
useless(const vector<int>& p_data)
{
for(auto elem:p_data)
{
less_q.emplace(elem);
more_q.emplace(elem);
}
}
};
I whould like to remove the duplication in the two struct's, the simpliest idea is to make the struct a template and provide two functor to do the comparison job:
template<typename Comp>
struct be_all
{
//Lot of stuff, better do not duplicate
int val;
be_all(int p_v):val{p_v}{}
bool operator<(const be_all<Comp>& p_other) const
{
return Comp()(val,p_other.val);
}
};
class comp_less
{
public:
bool operator()(int p_first,
int p_second)
{
return p_first < p_second;
}
};
class comp_more
{
public:
bool operator()(int p_first,
int p_second)
{
return p_first > p_second;
}
};
typedef be_all<comp_less> all_less;
typedef be_all<comp_more> all_more;
class useless
{
priority_queue<all_less> less_q;
priority_queue<all_more> more_q;
public:
useless(const vector<int>& p_data)
{
for(auto elem:p_data)
{
less_q.emplace(elem);
more_q.emplace(elem);
}
}
};
This work pretty well, now for sure i dont have any duplication in the struct code at the price of two additional function object. Please note that i'm very simplifying the implementation of operator<, the hipotetic real code does much more than just comparing two ints.
Then i was thinking about how to do the same thing using lambda (Just as an experiment).The only working solution i was able to implement is:
template<typename Comp>
struct be_all
{
int val;
function<bool(int,int)> Comparator;
be_all(Comp p_comp,int p_v):
Comparator(move(p_comp)),
val{p_v}
{}
bool operator<(const be_all& p_other) const
{
return Comparator(val, p_other.val);
}
};
auto be_less = [](int p_first,
int p_second)
{
return p_first < p_second;
};
auto be_more = [](int p_first,
int p_second)
{
return p_first > p_second;
};
typedef be_all<decltype(be_less)> all_less;
typedef be_all<decltype(be_more)> all_more;
class useless
{
priority_queue<all_less> less_q;
priority_queue<all_more> more_q;
public:
useless(const vector<int>& p_data)
{
for(auto elem:p_data)
{
less_q.emplace(be_less,elem);
more_q.emplace(be_more,elem);
}
}
};
This implementation not only add a new member to the data containing struct, but have also a very poor performance, i prepared a small test in which i create one instance for all the useless class i've show you here, every time i feed the constructor with a vector full of 2 milion integers, the results are the following:
Takes 48ms to execute the constructor of the first useless class
Takes 228ms to create the second useless class (functor)
Takes 557ms to create the third useless class (lambdas)
Clearly the price i pay for the removed duplication is very high, and in the original code the duplication is still there. Please note how bad is the performance of the third implementation, ten times slower that the original one, i believed that the reason of the third implementation being slower than the second was because of the additional parameter in the constructor of be_all... but:
Actually there's also a fourth case, where i still used the lambda but i get rid of the Comparator member and of the additional parameter in be_all, the code is the following:
template<typename Comp>
struct be_all
{
int val;
be_all(int p_v):val{p_v}
{}
bool operator<(const be_all& p_other) const
{
return Comp(val, p_other.val);
}
};
bool be_less = [](int p_first,
int p_second)
{
return p_first < p_second;
};
bool be_more = [](int p_first,
int p_second)
{
return p_first > p_second;
};
typedef be_all<decltype(be_less)> all_less;
typedef be_all<decltype(be_more)> all_more;
class useless
{
priority_queue<all_less> less_q;
priority_queue<all_more> more_q;
public:
useless(const vector<int>& p_data)
{
for(auto elem:p_data)
{
less_q.emplace(elem);
more_q.emplace(elem);
}
}
};
If i remove auto from the lambda and use bool instead the code build even if i use Comp(val, p_other.val) in operator<.
What's very strange to me is that this fourth implementation (lambda without the Comparator member) is even slower than the other, at the end the average performance i was able to register are the following:
48ms
228ms
557ms
698ms
Why the functor are so much faster than lambdas in this scenario? I was expecting lambda's to be at least performing good as the ordinary functor, can someone of you comment please? And is there any technial reason why the fourth implementation is slower than the third?
PS:
The compilator i'm using is g++4.8.2 with -O3. In my test i create for each useless class an instance and using chrono i take account of the required time:
namespace benchmark
{
template<typename T>
long run()
{
auto start=chrono::high_resolution_clock::now();
T t(data::plenty_of_data);
auto stop=chrono::high_resolution_clock::now();
return chrono::duration_cast<chrono::milliseconds>(stop-start).count();
}
}
and:
cout<<"Bad code: "<<benchmark::run<bad_code::useless>()<<"ms\n";
cout<<"Bad code2: "<<benchmark::run<bad_code2::useless>()<<"ms\n";
cout<<"Bad code3: "<<benchmark::run<bad_code3::useless>()<<"ms\n";
cout<<"Bad code4: "<<benchmark::run<bad_code4::useless>()<<"ms\n";
The set of input integers is the same for all, plenty_of_data is a vector full of 2 million intergers.
Thanks for your time
You are not comparing the runtime of a lambda and a functor. Instead, the numbers indicate the difference in using a functor and an std::function. And std::function<R(Args...)>, for example, can store any Callable satisfying the signature R(Args...). It does this through type-erasure. So, the difference you see comes from the overhead of a virtual call in std::function::operator().
For example, the libc++ implementation(3.5) has a base class template<class _Fp, class _Alloc, class _Rp, class ..._ArgTypes> __base with a virtual operator(). std::function stores a __base<...>*. Whenever you create an std::function with a callable F, an object of type template<class F, class _Alloc, class R, class ...Args> class __func is created, which inherits from __base<...> and overrides the virtual operator().
I'm working on some code and I have a section where I do a one off sort function. To implement it I decided it was easiest to overload the operator< function. What I would prefer to do is move the implementation of the sort closer to the actual call by using some sort of boost::bind, boost::phoenix, lambda or some other type of implementation. Unfortunately I don't have access to new C++11 functionality. Below is some example code.
// In a header
struct foo
{
char * a;
char * c_str() { return a; }
}
// In a header
struct bar
{
foo * X;
bar(foo * _X) : X(_X) {}
bool operator < (const bar& rhs) const
{
return std::string(X->c_str()) < std::string(rhs.X->c_str());
}
};
struct bars : public std::vector<bar> { ... some stuff };
// Some other header
bars Bs;
// A cpp file
... other stuff happens that fills the Xs vector with objects
...::Function()
{
// Current use and it works fine
std::sort(Bs.begin(), Bs.end())
// Would like something that accomplishes this:
// std::sort(Bs.begin(), Bs.end(),
// std::string(lhs.X->c_str()) < std::string(rhs.X->c_str()))
// A non-working example of what I'm trying to do
// std::sort(Xs.begin(), Xs.end(),
// std::string((bind(bar::X->c_str(), _1)) <
// std::string((bind(bar::X->c_str(), _2)) )
}
I get lost when trying to figure out how to access the member pointers, member function and then cast the result all within a boost::bind function.
Thank you for your help.
I'm sure you can twist your way out of this using ample helpings of
Boost Phoenix bind and lambda
Boost Bind protect
However, I've learned to avoid these situations. Edit In fact, see below for one such contraption. I find this very very error prone and hard to reason about.
What you're seeing is, in essence, a violation of the Law Of Demeter. If you "just" wrote the code (not in a lambda), already it would be handling too many tasks.
So the first thing I'd do is rethink the class design.
The second thing I'd do is /extract/ different responsibilities from your comparator. Notice, that the comparator does three things:
access the c_str() of the X in lhs
access the c_str() of the X in rhs
compare the two
The first two steps are clear candidates for extraction. Let's write the generic comparer that remains first:
template <typename F>
struct compare_by_impl {
compare_by_impl(F f = F{}) : _f(std::move(f)) {}
template <typename T, typename U>
bool operator()(T const& a, U const& b) const {
return _f(a) < _f(b);
}
private:
F _f;
};
As always, it's nice to have factory function that will deduce the accessor type (in case you can get away with just using Phoenix there, it will save you specifying the (arcane) typenames involved in the expression templates):
template <typename Accessor>
compare_by_impl<Accessor> comparer_by(Accessor&& f) {
return compare_by_impl<Accessor>(std::forward<Accessor>(f));
}
Now you could already move the implementation with your sort call:
void Function()
{
struct accessX_c_str {
std::string operator()(bar const& b) const {
return b.X->c_str();
}
};
std::sort(Bs.begin(), Bs.end(), comparer_by(accessX_c_str()));
}
I'd personally leave it there.
Here's some more twisted contraptions:
// to avoid `comparer_by`
std::sort(Bs.begin(), Bs.end(), phx::bind(accessX_c_str(), arg1) < phx::bind(accessX_c_str(), arg2));
// to avoid any helper types (!?!?!? untested!)
std::sort(Bs.begin(), Bs.end(),
phx::construct<std::string>(phx::bind(&foo::c_str, phx::lambda [ phx::bind(&bar::X, arg1) ](arg1)))
< phx::construct<std::string>(phx::bind(&foo::c_str, phx::lambda [ phx::bind(&bar::X, arg1) ](arg2)))
);