I posted earlier about a way to provide optional functionality through traits. I used operator [] as the example. As I have been using the library I found some issues with that approach. The main issue was that operator[] is not a template method, being on a templates class is not enough. This meant that using SFINAE to remove the function entirely when the trait was not specified was not possible. Another issue was that some compilers would complain if auto was used on free-functions. These are both addressed now, here is the latest.

template<typename TypeTag, typename ResourceType>
decltype(unique_t_at(
instance_of<ResourceType>::value,
instance_of<size_t>::value,
TypeTag()))
optional_unique_t_at(
ResourceType && resource,
size_t index,
int)
{
return unique_t_at(
std::forward<ResourceType>(resource),
index,
TypeTag());
}

struct no_indexing_support {};

template<typename TypeTag>
no_indexing_support
optional_unique_t_at(...)
{
return no_indexing_support();
}

template<typename TypeTag>
class unique_t {
private:
typedef
decltype(optional_unique_t_at<TypeTag>(
instance_of<type>::value,
instance_of<size_t>::value,
0))
optional_at_result;
public:
...
optional_at_result operator[](
size_t at) {
return optional_unique_t_at<TypeTag>(
t,
at,
0);
}
private:
type t;
};

Lines 1-24 take care of routing to the trait implementation, when it exists, and a default that provides a suitable error when used. The auto keyword is not used, as a consequence we cannot use the parameters and must synthesize the values used in the decltype. These free-functions are templates and are therefore able to use SFINAE. Here we can see most of the adjustments that were needed to get optional traits working.