I am trying to use 'decltype' on a variadic function template to get its return value type and then use it to define a member variable. But I keep getting this error:
D:\Qt Projects\OpenGL_PhysicsSim\lib\Physics Effects\include\ParticleList.hpp:89: error: cannot convert 'std::tuple<std::uniform_real_distribution<double>, std::uniform_real_distribution<double>, std::uniform_real_distribution<double> >' to 'int' in assignment
distributionTuple = createDistribution<Type, Types...>(meanValue, meanValues..., varianceValue, varianceValues...);
Basically, the decltype fails and declare distributionTuple as int rather than deduce return type of createDistribution.
template<typename AttributeType, typename Type, typename ...Types>
class ParticleAttributeGenerator
{
private:
template<typename T>
auto createDistribution(T meanValue, T varianceValue)
{
static_assert(
std::is_integral<Type>::value || std::is_floating_point<Type>::value,
"Type should be either integral value or floating point value");
using distType = typename std::conditional< std::is_integral<T>::value,
std::uniform_int_distribution<>,
std::uniform_real_distribution<> >::type;
T a = meanValue - varianceValue;
T b = meanValue + varianceValue;
return std::tuple<distType>(distType(a,b));
}
template<typename Tfirst, typename ...Trest>
auto createDistribution(Tfirst meanValue, Trest... meanValues, Tfirst varianceValue, Trest... varianceValues)
{
static_assert(
std::is_integral<Type>::value || std::is_floating_point<Type>::value,
"Type should be either integral value or floating point value");
using distType = typename std::conditional< std::is_integral<Tfirst>::value,
std::uniform_int_distribution<>,
std::uniform_real_distribution<> >::type;
Tfirst a = meanValue - varianceValue;
Tfirst b = meanValue + varianceValue;
static_assert((sizeof...(meanValues)) == (sizeof...(varianceValues)), "number of meanValues and varianceValues should match!");
return std::tuple_cat(std::tuple<distType>(distType(a,b)), createDistribution<Trest...>(meanValues..., varianceValues...));
}
public:
ParticleAttributeGenerator(Type meanValue, Types... meanValues, Type varianceValue, Types... varianceValues)
{
distributionTuple = createDistribution<Type, Types...>(meanValue, meanValues..., varianceValue, varianceValues...); // 89 : error
}
private:
//using result_type_t = typename std::result_of<createDistribution(Type, Types..., Type, Types...)>::type;
decltype (createDistribution<Type, Types...>(Type, Types..., Type, Types...)) distributionTuple;
//decltype (createDistribution<Type, Types...>(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f)) distributionTuple;
};
It works when I provide all the values of arguments of createDistribution, but that is not the behavior I was looking for. Since I don't know how many parameters there will be for that function, it has to stay as variadic template function.
Example of how I plan to use the class template:
ParticleAttributeGenerator<glm::vec3, float, float, float> example1(3.0f, 1.0f, 3.0f, 1.0f, 3.0f, 1.0f);
ParticleAttributeGenerator<glm::u8vec4, uint8_t, uint8_t, uint8_t, uint8_t> example2(3, 2, 25, 5, 51, 12, 32, 3);
if I don't have any member variable and use distributedTuple as:
auto distributionTuple = createDistribution<Type, Types...>(meanValue, meanValues..., varianceValue, varianceValues...);
It compiles, therefore I believe createDistribution manages to define tuple recursively. But that is no use for me. There must be something wrong that I am missing.
I use GCC 4.9.2 in -std=c++14 mode.