How to determine whether a C++ template parameter stores unique keys? - c++

I'm working on some custom algorithm optimization, using containers.
My algorithms need to support all standard containers, as well as custom containers.
Right now, I'm working on making this algorithm work with set containers.
(Set containers require special handling, since individual elements are always const.)
The problem is, I need to separate the code paths, based on whether the set container stores unique keys.
(Unique keys obviously necessitate changes to the algorithm.)
Does the C++ standard library provide any conditional templates that can do this?
(Similar to std::is_signed_v)
Or is there another way to make this determination?
template < typename _SET_T >
void foo ( )
{
if ( unique keys ) // e.g. if _SET_T is a std::set or std::unordered_set
{
// optimize algorithm to account for uniqueness of keys
}
else // e.g. if _SET_T is a std::multiset or std::unordered_multiset
{
// optimize algorithm to account for NON-uniqueness of keys
}
}

There's no such concept and/or trait in the standard library, you'll have to write your own:
template <class T>
struct has_unique_keys : std::false_type {};
template <class... P>
struct has_unique_keys<std::set<P...>> : std::true_type {};
template <class... P>
struct has_unique_keys<std::map<P...>> : std::true_type {};
// ...
The base case makes the assumption that the keys are not unique because I suppose that the unique-keys-expecting algorithm would fail on multiple-keys containers, while the other way around would merely be slower.

You could do it by introducing your own traits and a little indirection.
Example Code
#include <iostream>
#include <set>
#include <unordered_set>
template<typename T>
struct HasUniqueKeys : std::true_type
{
};
template<typename T>
struct HasUniqueKeys<std::multiset<T>> : std::false_type
{
};
template<typename T>
struct HasUniqueKeys<std::unordered_multiset<T>> : std::false_type
{
};
template<bool HasUniqueKeys>
struct FooHelper
{
static void foo()
{
std::cout << "foo(multi_keys)\n";
}
};
template<>
struct FooHelper<true>
{
static void foo()
{
std::cout << "foo(unique_keys)\n";
}
};
template<typename T>
void foo(T keys)
{
FooHelper<HasUniqueKeys<T>::value>::foo();
}
int main()
{
std::set<int> set;
std::unordered_set<int> uset;
std::multiset<int> mset;
std::unordered_multiset<int> umset;
foo(set);
foo(uset);
foo(mset);
foo(umset);
return 0;
}
Example Output
foo(unique_keys)
foo(unique_keys)
foo(multi_keys)
foo(multi_keys)
Live Example

Related

How is nested template specialization done C++

I have a templated function defined as:
template<typename TObject> TObject Deserialize(long version, const Value &value)
what I need to do, is to write a specialization which would take vector defined as:
template<typename TNum, int cnt> class Vec
and still has access to cnt and TNum.
I have unsuccesfully tried
template<typename TNum, int cnt> Vec<TNum, cnt> Deserialize<Vec<TNum, cnt>>(long version, Value &value)
resulting in error: illegal use of explicit template arguments
What is the correct way to do it?
Usually, the correct answer to dealing with function templates and needing to partially specialize them, is to simply overload them instead. In this case this trick doesn't work directly because there are no arguments that depend on the template parameter, i.e. the template parameter is explicitly specified and not deduced. However, you can forward along to implementation functions, and make overloading work by using a simple tag struct.
#include <functional>
#include <iostream>
#include <type_traits>
#include <vector>
#include <array>
template <class T>
struct tag{};
template<typename TObject>
TObject Deserialize_impl(long version, tag<TObject>) {
std::cerr << "generic\n";
return {};
}
template<typename T, std::size_t N>
std::array<T,N> Deserialize_impl(long version, tag<std::array<T,N>>) {
std::cerr << "special\n";
return {};
}
template<typename TObject>
TObject Deserialize(long version) {
return Deserialize_impl(version, tag<TObject>{});
}
int main() {
Deserialize<int>(0);
Deserialize<std::array<int,3>>(0);
return 0;
}
Live example: http://coliru.stacked-crooked.com/a/9c4fa84d2686997a
I generally find these approaches strongly preferable to partial specialization of a struct with a static method (the other major approach here) as there are many things you can take advantage with functions, and it behaves more intuitively compared to specialization. YMMV.
While the functional tag-dispatch is a nice approach, here's a class specialization version for comparison. Both have their use, and I don't think either is an inherently regrettable decision but maybe one matches your personal style more.
For any class you write that needs a custom deserialize handler, just write a specialization of the Deserializer class:
#include <iostream>
#include <string>
using namespace std;
using Value = std::string;
// default deserialize function
template <typename TObject>
struct Deserializer {
static TObject deserialize(long version, const Value &value) {
std::cout << "default impl\n";
return TObject();
}
};
// free standing function (if you want it) to forward into the classes
template <typename TObject>
TObject deserialize(long version, const Value &value) {
return Deserializer<TObject>::deserialize(version, value);
}
// Stub example for your Vec class
template<typename TNum, int cnt> class Vec { };
// Stub example for your Vec deserializer specialization
template <typename TNum, int cnt> struct Deserializer<Vec<TNum, cnt>> {
static auto deserialize(long version, const Value &value) {
std::cout << "specialization impl: cnt=" << cnt << "\n";
return Vec<TNum, cnt>();
}
};
int main() {
Value value{"abcdefg"};
long version = 1;
deserialize<int>(version, value);
deserialize<Vec<int, 10>>(version, value);
}
Ideally in this situation, Vec should reflect its own template parameters as members Vec::value_type and Vec::size() which should be constexpr.
If the class fails to provide its own properties in its own interface, the next best thing is to define your own extension interface. In this situation, you can have separate metafunctions (like accessor functions), or a traits class (like a helper view class). I'd prefer the latter:
template< typename >
struct vector_traits;
template< typename TNum, int cnt >
struct vector_traits< Vec< TNum, cnt > > {
typedef TNum value_type;
constexpr static int size = cnt;
};
template<typename TVec> TVec Deserialize(long version, Value &value) {
typedef vector_traits< TVec > traits;
typedef typename traits::value_type TNum;
constexpr static int cnt = traits::size;
…
}
This solution fits into any existing function, and even makes the signatures cleaner. Also, the function is more flexible because you can adapt it by adding traits specializations instead of entire new overloads.

Template class with method depending on template parameter

I am writing a class designed to shoot random 3D vectors, but I use several geometric libraries in my projects (one included in the 3D simulation, one included in the analysis framework, one which is not included in a more-than-1-GB framework...). Each of these libraries has its own vector definition, with different names for the same method, such has getX(), GetX(), Get(0)... to get the first Cartesian coordinate. But sometimes a common naming convention has been adopted and some method names are the same across two or more libraries.
Of course I want to use this code for any of these vectors, so I implemented a template class. The problem is the following: how do I adapt my code to all these method names, without specializing my class for each implementation (some share the same method names) ?
I managed to write a class using a method or another, now I would like to generalize to any number of method. Something which says: "If you have method 1, use this implementation, if you have method 2, use this other one,... and if you have none, then compilation error".
Currently the class looks like (reduced to the part shooting a random direction):
// First some templates to test the presence of some methods
namespace detail_rand {
// test if a class contains the "setRThetaPhi" method
template<class T>
static auto test_setRThetaPhi(int) ->
decltype(void(std::declval<T>().setRThetaPhi(0.,0.,0.)),
std::true_type{});
template<class T>
static auto test_setRThetaPhi(float)->std::false_type;
}
// true_type if the class contains the "setRThetaPhi" method
template<class T>
struct has_setRThetaPhi : decltype(detail_rand::test_setRThetaPhi<T>(0)) {};
// The actual class
template<class vector>
class Random
{
// everything is static for easy use, might change later
private:
Random() = delete;
Random(Random&) = delete;
// the distribution, random generator and its seed
static decltype(std::chrono::high_resolution_clock::now().time_since_epoch().count()) theSeed;
static std::default_random_engine theGenerator;
static std::uniform_real_distribution<double> uniform_real_distro;
// Shoot a direction, the actual implementation is at the end of the file
private: // the different implementations
static const vector Dir_impl(std::true_type const &);
static const vector Dir_impl(std::false_type const &);
public: // the wrapper around the implementations
inline static const vector Direction() {
return Dir_impl(has_setRThetaPhi<vector>());
}
};
/// initialisation of members (static but template so in header)
// the seed is not of cryptographic quality but here it's not relevant
template<class vector>
decltype(std::chrono::high_resolution_clock::now().time_since_epoch().count())
Random<vector>::theSeed =
std::chrono::high_resolution_clock::now().time_since_epoch().count();
template<class vector>
std::default_random_engine Random<vector>::theGenerator(theSeed);
template<class vector>
std::uniform_real_distribution<double> Random<vector>::uniform_real_distro(0.,1.);
/// Implementation of method depending on the actual type of vector
// Here I use the "setRThetaPhi" method
template<class vector>
const vector Random<vector>::Dir_impl(std::true_type const &)
{
vector v;
v.setRThetaPhi(1.,
std::acos(1.-2.*uniform_real_distro(theGenerator)),
TwoPi()*uniform_real_distro(theGenerator));
return std::move(v);
}
// Here I use as a default the "SetMagThetaPhi" method
// but I would like to test before if I really have this method,
// and define a default implementation ending in a compilation error
// (through static_assert probably)
template<class vector>
const vector Random<vector>::Dir_impl(std::false_type const &)
{
vector v;
v.SetMagThetaPhi(1.,
std::acos(1.-2.*uniform_real_distro(theGenerator)),
TwoPi()*uniform_real_distro(theGenerator));
return std::move(v);
}
Something which says: "If you have method 1, use this implementation, if you have method 2, use this other one,... and if you have none, then compilation error".
I wrote an article that explains how to implement exactly what you need in C++11, C++14 and C++17: "checking expression validity in-place with C++17".
I will synthesize the C++11 and C++14 solutions below - you can use them to normalize all the interfaces you're dealing with by wrapping them inside a single "common" one. You can then implement your algorithms on the "common" interface.
Assume that you have:
struct Cat { void meow() const; };
struct Dog { void bark() const; };
And you want to create a function template make_noise(const T& x) that calls x.meow() if valid, otherwise x.bark() if valid, otherwise produces a compiler error.
In C++11, you can use enable_if and the detection idiom.
You will need to create a type trait for every member you wish to check the existence of. Example:
template <typename, typename = void>
struct has_meow : std::false_type { };
template <typename T>
struct has_meow<T, void_t<decltype(std::declval<T>().meow())>>
: std::true_type { };
Here's an usage example using enable_if and trailing return types - this technique makes use of expression SFINAE.
template <typename T>
auto make_noise(const T& x)
-> typename std::enable_if<has_meow<T>{}>::type
{
x.meow();
}
template <typename T>
auto make_noise(const T& x)
-> typename std::enable_if<has_bark<T>{}>::type
{
x.bark();
}
In C++14, you can use generic lambdas and an implementation of static_if (here's a talk I gave at CppCon 2016 about a possible one) to perform the check with an imperative-like syntax.
You need a few utilities:
// Type trait that checks if a particular function object can be
// called with a particular set of arguments.
template <typename, typename = void>
struct is_callable : std::false_type { };
template <typename TF, class... Ts>
struct is_callable<TF(Ts...),
void_t<decltype(std::declval<TF>()(std::declval<Ts>()...))>>
: std::true_type { };
// Wrapper around `is_callable`.
template <typename TF>
struct validity_checker
{
template <typename... Ts>
constexpr auto operator()(Ts&&...) const
{
return is_callable<TF(Ts...)>{};
}
};
// Creates `validity_checker` by deducing `TF`.
template <typename TF>
constexpr auto is_valid(TF)
{
return validity_checker<TF>{};
}
After that, you can perform all of your checks inside a single overload of make_noise:
template <typename T>
auto make_noise(const T& x)
{
auto has_meow = is_valid([](auto&& x) -> decltype(x.meow()){ });
auto has_bark = is_valid([](auto&& x) -> decltype(x.bark()){ });
static_if(has_meow(x))
.then([&x](auto)
{
x.meow();
})
.else_if(has_bark(x))
.then([&x](auto)
{
x.bark();
})
.else_([](auto)
{
// Produce a compiler-error.
struct cannot_meow_or_bark;
cannot_meow_or_bark{};
})(dummy{});
}
Some macro black magic and if constexpr allow you to write this in C++17:
template <typename T>
auto make_noise(const T& x)
{
if constexpr(IS_VALID(T)(_0.meow()))
{
x.meow();
}
else if constexpr(IS_VALID(T)(_0.bark()))
{
x.bark();
}
else
{
struct cannot_meow_or_bark;
cannot_meow_or_bark{};
}
}
You could solve this by introducing your own names for the operations. Do this by creating a trait class and specialising it for each of the libraries. Something like this:
template <class Vector>
struct VectorTraits;
template <>
struct VectorTraits<Lib1::Vector>
{
static auto getX(const Lib1::Vector &v) { return v.GetX(); }
// ... etc.
};
template <>
struct VectorTraits<Lib2::Vector>
{
static auto getX(const Lib2::Vector &v) { return v.Get(0); }
// ... etc.
};
//Usage:
template <class vector>
auto norm2(const vector &v)
{
using V = VectorTraits<vector>;
return V::getX(v) * V::getX(v) + V::getY(v) + V::getY(v);
}
If you want static assertions for the unsupported operations, you can put them into the unspecialised template:
template <class T>
struct False : std::false_type {};
template <class Vector>
struct VectorTraits
{
static void getX(const Vector &)
{
static_assert(False<Vector>::value, "This type does not support getting x");
}
};

Use same template function for different arguments?

If I have a complicated function that I want to use for two collections with matching interfaces (at least as far as the function in question is concerned) is there a way to just re-use the template code?
For example:
void DoSomethingIntense(std::vector<blah> myBlah);
void DoSomethingIntense(std::array<blah> myBlah);
If I use begin, end, size, and other functions that both array and vector have in common, is there a way to re-use the body of DoSomethingIntense without typing it twice (or, heaven forbid, stuffing it into a macro)?
(Please do not nitpick the example code, it doesn't help anybody)
UPDATE: My apologies, I neglected to mention that the function in question has other implementations for classes that do not match this signature; just making every argument use the code that works for these two is not an option.
I think the iterator solution might be best in that scenario.
Yes, use a template.
template <typename Container>
void DoSomethingIntense(Container blah) { // Might be better as Container const &
// write code using blah.begin() or whatever
}
You might be able to make it even more generic, following the example of STL, by supporting a general iterator range rather than specifically a container:
template <typename Iterator>
void DoSomethingIntense(Iterator begin, Iterator end);
Yes, you can achieve that by using templates:
template<typename T>
void DoSomethingIntense(const T &myBlah);
EDIT:
If I get your update right then I would say make use of SFINEA:
template<typename T>
struct is_vector : std::false_type {};
template<typename T, typename A>
struct is_vector<std::vector<T, A>> : std::true_type {};
template<typename T>
struct is_array : std::false_type {};
template<typename T, size_t N>
struct is_array<std::array<T, N>> : std::true_type {};
// add more if you want or define a macro
template<typename T>
std::enable_if_t<is_vector<T>::value || is_array<T>::value, void>
DoSomethingIntense(const T &myBlah)
{
}
int main()
{
std::vector<int> v;
DoSomethingIntense(v); // OK
std::array<float, 5> a;
DoSomethingIntense(a); // OK
std::queue<int> q;
DoSomethingIntense(q); // ERROR
}
You can mix templates / overloads. No problem.
For example:
template <typename T>
void DoSomethingIntense(T myBlah) {
}
void DoSomethingIntense(MyCustomClass myBlah) {
}
Then it will use the non-template version for argument type MyCustomClass and the template version for anything else (like vector or array)
Moreover, you can use std::enable_if to restrict the range of possible template arguments. See also this question.

How to check whether a container is stable

std::vector is an unstable container, i.e. by resizing the vector, iterators might become invalidated.
In contrast, std::list or boost::container::stable_vector are stable containers which keep the iterators valid until the removal of the corresponding element.
Is there a way to check whether a given container is stable? For instance, if I have something like
template<template <typename A, typename B=std::allocator<A> > class T=std::list>
class Foo
{
}
Is it possible to allow only for stable containers and forbid the unstable ones?
I don't think there is anything available providing such information, but you could write your own trait. However, you will need to specialize it for every stable container that may be used, which is perhaps not an option.
#include <boost/container/vector.hpp>
#include <iostream>
#include <type_traits>
#include <list>
#include <vector>
template <template <typename...> class Container>
struct is_stable
: std::false_type
{};
template <>
struct is_stable<std::list>
: std::true_type
{};
template <>
struct is_stable<boost::container::stable_vector>
: std::true_type
{};
template<template <typename...> class Container = std::list>
class Foo
{
static_assert(is_stable<Container>::value, "Container must be stable");
};
int main()
{
Foo<std::list> f1; // ok
Foo<std::vector> f2; // compiler error
}
I don't think there is a way you can automatically detect that a container is stable, without resorting to manual specialization.
Just for fun, I tried writing what the concept/axiom for stability would look like (concepts and axioms are an extension to the language that were considered for inclusion in C++11):
concept StableGroup<typename C, typename Op>
: Container<C>
{
void operator()(Op, C, C::value_type);
axiom Stability(C c, Op op, C::size_type index, C::value_type val)
{
if (index <= c.size())
{
auto it = std::advance(c.begin(), index);
op(c, val);
return it;
}
<->
if (index <= c.size())
{
op(c, val);
return std::advance(c.begin(), index);
}
}
}
If think this correctly captures the requirement that every iterator over the original container is equivalent to the corresponding iterator over the modified container. Not sure this is very useful, but coming up with such axioms is an interesting exercise :)!

Reflection in known set of classes

I am trying to iterate through an object hierarchy and the object hierarchy is composed of a known set of classes combined using composition. I would like to build an object model to show the hierarchy / composition graphically. The composition is done based on few rules but it is fluid and flexible.
Quite a few classes (25+) are available and the number of building blocks is increasing. If I search each type in every other type then we have a significantly large number of combinations possible.
I could build a large table where I search for each of the other objects for a given type and recursively build the object model but may be there is a better way and so here I am asking the experts.
Is it possible to know if a function / member variable is present on a particular type at runtime.
My sample code is shown below :
#include <iostream>
struct Generic {};
struct SimpleType {int toString(){return 0;}};
enum ETypeVal{eVal1 = 0, eVal2 = 1, eVal3 = 2};
template <typename ETypeVal val>
struct Hello
{
int toString(){return 0;}
};
template <> struct Hello<eVal2>
{
int toString(){return 1;}
};
template <> struct Hello<eVal3>
{
};
template <class Type>
class TypeHasToString
{
public:
typedef bool Yes;
typedef short No;
static bool const value = (sizeof(HasToString<Type>(0)) == sizeof(Yes));
private:
template <typename T, T> struct TypeCheck;
template <typename T> struct ToString
{
typedef int (T::*fptr)();
};
template <typename T> static Yes HasToString(TypeCheck< typename ToString<T>::fptr, &T::toString >*);
template <typename T> static No HasToString(...);
};
int main(int argc, char *argv[])
{
// all this works fine
std::cout << TypeHasToString<Generic>::value << std::endl;
std::cout << TypeHasToString<SimpleType>::value << std::endl;
std::cout << TypeHasToString<Hello<eVal1>>::value << std::endl;
std::cout << TypeHasToString<Hello<eVal2>>::value << std::endl;
std::cout << TypeHasToString<Hello<eVal3>>::value << std::endl;
// Unable to deduce for type that are not known at compile time
// Is it possible to remove this limitation ?
for(int val = eVal1; val <= eVal3; val++)
{
std::cout << TypeHasToString< Hello< (ETypeVal)val > >::value << std::endl;
}
return 0;
}
I've used boost::mpl to do the iteration and printing of the values. Most of this should be possible without any of those, but I heavily recommend using it. Also I've fixed some things in your code. You might also want to use BOOST_HAS_XXX instead of your homebrew solution (your SFINAE style is rather awkward).
#include <iostream>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/for_each.hpp>
struct Generic {};
struct SimpleType {int toString(){return 0;}};
enum ETypeVal{ eVal1 = 0, eVal2 = 1, eVal3 = 2};
template <ETypeVal val>
struct Hello
{
int toString(){return 0;}
};
template <> struct Hello<eVal2>
{
int toString(){return 1;}
};
template <> struct Hello<eVal3>
{
};
template <class Type>
class TypeHasToString
{
public:
typedef bool Yes;
typedef short No;
private:
template <typename T, T> struct TypeCheck;
template <typename T> struct ToString
{
typedef int (T::*fptr)();
};
template <typename T> static Yes HasToString(TypeCheck< typename ToString<T>::fptr, &T::toString >*);
template <typename T> static No HasToString(...);
public:
static bool const value = (sizeof(HasToString<Type>(0)) == sizeof(Yes));
};
template<typename val>
struct make_hello { typedef Hello< ETypeVal(val::value)> type; };
struct print_seq {
template<typename T>
void operator()(const T&) const {
std::cout << T::value << std::endl;
}
};
int main()
{
using namespace boost::mpl;
// maybe have a last enum here
typedef range_c<int, eVal1, eVal3 + 1>::type range;
// range has no clear so we need the inserter
typedef transform<range, make_hello<_1>, back_inserter< vector0<> > >::type hellos;
typedef transform< hellos, TypeHasToString<_1> >::type booleans;
// namespace for clarity
boost::mpl::for_each<booleans>( print_seq() );
return 0;
}
We don't have run-time reflection in C++. But we have different stuff, that most C++ programmers like better than reflection ;-).
If I understand your question, you need to build some sort of object browser, and you know all your object types. By "you know all your object types" I mean "you won't get an object as something at the other end of a pointer from a dll you didn't code".
So, maybe you can use boost::fusion? Said library is designed for iterating through aggregates, and while doing so, retrieving both data and type of each aggregate member. It is like iterators over struct members, if I have to put it in a flowery way. You can of course use it with your custom types.
You can't know at runtime if you don't at compile time. You have the code to know at compile time for one function. You could just make a macro out of it to have it for any function you want to check. (Macro disclaimer: in this case macros are good, that's how BOOST_MPL_HAS_XXX_TEMPLATE_DEF works).
Alternatively, there's boost::fusion as mentionned by dsign. But I prefer another one: boost::reflect (not actully in boost more info here). The macro syntax is easier (you don't need to mention the type in the macro) and the code is very lightweight. Then there's the feature complete boost::mirror (download here), not yet in boost, that is much more complete and even has a code generator to create the macro calls for you and a java style runtime reflection.
I think that you need the runtime polymorphism in this case. Use interfaces instead of templates for such kind of problems. Interfaces will give the knowledge about of the methods in your object but will say nothing about the member variables. So there is no reflection available in standard c++ (the only thing that c++ provides is the type_info operator which might help you in some cases), you could try to find some extensions for your compiler which will give you the reflection opportunities.