Yes, it seems there is something going wrong with non basic types. However, I found a solution that seems to work :
#include <functional>
#include <type_traits>
#include <string>
template <typename T>
class Distribution {
typedef std::function<T()> FactoryFn;
public:
// template <typename U, class = typename std::enable_if<std::is_convertible<U, T>::value>::type>
// Distribution(U cst)
template <typename U>
Distribution(U cst, typename std::enable_if<std::is_convertible<U, T>::value>::type* = 0)
: m_factory()
{
T copy = cst;
// m_factory = [copy] () { return copy; }; // FIX : replace this line
m_factory = [cst] () { return cst; }; // with this one.
}
private:
FactoryFn m_factory;
};
struct Foo {
char c, d;
Foo() : c(0), d(0) { }
Foo(char c, char d) : c(c), d(d) { }
};
struct Bar {
char c, d;
Bar() : c(0), d(0) { }
Bar(char c, char d) : c(c), d(d) { }
Bar(Bar const& bar) : c(bar.c), d(bar.d) { }
Bar(Bar && bar) : c(std::move(bar.c)), d(std::move(bar.d)) { }
Bar& operator=(Bar const bar) { c = bar.c; d = bar.d; return *this; }
Bar& operator=(Bar && bar) { c = std::move(bar.c); d = std::move(bar.d); return *this; }
~Bar() { }
};
int main(int argc, const char * argv[])
{
char someChar = 58;
Distribution<int> distInt(someChar);
std::string someString = "42";
// Distribution<int> distInt2(someString); // Error, no matching ctor (as expected), no crash here
Distribution<std::string> distStr(someString); // _WAS_ CRASHING HERE
Distribution<float> distFloat(3.f);
Distribution<double> distDouble(3.0);
Foo someFoo = {'a', 'A'};
Distribution<Foo> distFoo(someFoo); // _WAS_ CRASHING HERE
Bar someBar = {'b', 'B'};
Distribution<Bar> distBar(someBar); // _WAS_ CRASHING HERE
[someBar]() { return someBar; }();
return 0;
}
As you can see, before the fix, only basic types like int or double worked. Now, if we apply the fix everything works fine.
I test it out on Thor and clang doesn't crash anymore.
Replace line 68 with
mFactory = [constant] () { return constant; };
and remove line 67 as it's no longer needed.