Declaring static auto function pointers in traits template - c++

I have a couple of functions for different data types that I want to use in a template depending on the data type of the template parameter. I declared a helper template struct traits and specialized it for the corresponding data types.
My question is: is it possible to avoid writing the exact function signatures in these specializations? Additionally, is it possible to avoid defining these functions outside of the template declaration and still have them static?
The very simplified example of what I want to do is below. The syntax that I would like to use is commented out, but it clearly doesn't compile.
#include <iostream>
int f() { return 1; }
double g() { return 2.3; }
template<typename T>
struct traits;
template<>
struct traits<int> {
// static auto func = f;
int(*func)() = f;
};
template<>
struct traits<double> {
// static auto func = g;
double(*func)() = g;
};
template<typename T>
struct traits_user {
void output() {
// std::cout << traits<T>::func() << " ";
std::cout << traits<T>().func() << " ";
}
};
int main()
{
traits_user<int>().output();
traits_user<double>().output();
}
Edit
While answer by #RSahu is actually perfect, I cannot use it because I'm stuck with VS2013 for some time more. A solution suitable for VS2013 would be very welcome.

You can use:
static auto constexpr func = f;
and
static auto constexpr func = g;
I got the following error in g++ when I tried to compile without the constexpr.
g++ -std=c++11 -Wall socc.cc -o socc
socc.cc:17:24: error: ‘constexpr’ needed for in-class initialization of static data member ‘double (* traits<double>::func)()’ of non-integral type [-fpermissive]
static auto func = g;
Without support for constexpr, one work around is:
template<>
struct traits<int> {
static double func()
{
return f();
}
};
template<>
struct traits<double> {
static double func()
{
return g();
}
};

If you can't use auto, you can probably still use decltype and a type alias:
template<> struct traits<int> {
using F = decltype(&f);
const static F func;
};
const traits<int>::F traits<int>::func= f;
Whether that is better or worse than the explicit approach is for you to decide.
You can of course also omit the type alias, if you don't need it anywhere else:
template<> struct traits<int> {
const static decltype(&f) func;
};
const decltype(&f) traits<int>::func = f;

Related

Static member definition of complex type of a template class with SFINAE

It is fairly standard way to declare and define a static const member of a complex type of a template class. However, I would to use SFINAE patter in my class. And that leads to this error: template definition of non-template 'const std::array<unsigned int, 2ul> Message<Self>::kData'. Removing SFINAE resolves the error.
Here is the code:
#include <iostream>
#include <type_traits>
#include <array>
using namespace std;
template <class Self, typename = std::enable_if_t<std::is_class<Self>::value>>
class Message
{
public:
bool Verify() const { return static_cast<const Self *>(this)->Verify(); }
static const std::array<uint32_t, 2> kData;
};
class Command : public Message<Command>
{
public:
bool Verify() {
std::cout << "Command::Verify";
return true;
}
};
template <class Self, typename = std::enable_if_t<std::is_class<Self>::value>>
const std::array<uint32_t, 2> Message<Self>::kData = { 12, 13 };
int main()
{
Command cmd;
cout << "Data: " << cmd.kData[0] << endl;
return 0;
}
Live code is here.
What is the proper syntax to still use SFINAE and properly define the static constant?
What is the proper syntax to still use SFINAE and properly define the static constant?
Simply using a generic type T
// ............................V
template <class Self, typename T>
const std::array<uint32_t, 2> Message<Self, T>::kData = { 12, 13 };
// .......................................^^^
Template default types/values aren't used in external definitions.

Declaring class member with deduced type

I have a code that uses type deduction like this:
template <typename... Ttypes>
Tuple<Ttypes...> makeTuple(Ttypes... args) {
Tuple<Ttypes...> result;
fillTuple<0>(result, args...);
return result;
}
I want to encapsulate the result to a class which is not a class template. The only way, and this is reasonable, is to have it as a static const member like this:
struct A {
static const auto t = makeTuple(1,2,3,'c');
};
and I get: error: in-class initializer for static data member of type 'const Tuple<int, int, int, char>' requires 'constexpr' specifier static const auto tuple = makeTuple(1,2,3,'c');.
If I use
struct A {
static const auto constexpr t = makeTuple(1,2,3,'c');
};
I get error: constexpr variable 'tuple' must be initialized by a constant expression.
Moreover, using constexpr is not good for me, because I' like to use non-literal types in a tuple.
Compiler Clang with -std=c++14.
Is there a way to get what I want?
Something along these lines, perhaps:
struct A {
using TupleType = decltype(makeTuple(1,2,3,'c'));
static const TupleType t;
};
// In a .cpp file
const A::TupleType A::t = makeTuple(1,2,3,'c');
Somewhat more elaborate, but avoids some repetition:
struct A {
static auto MakeMyTuple() { return makeTuple(1,2,3,'c'); }
using TupleType = decltype(MakeMyTuple());
static const TupleType t;
};
// In a .cpp file
const A::TupleType A::t = A::MakeMyTuple();
This way, arguments to makeTuple are all in one place.
You should be able to accomplish this without declaring the member static.
auto is useful for type deduction when it is also being initialized. If declaration is needed prior to initialization you can use decltype instead.
GeeksForGeeks has a good introduction to decltype.
https://www.geeksforgeeks.org/type-inference-in-c-auto-and-decltype/
#include <iostream>
#include <tuple>
#include <memory>
using namespace std;
template<typename... Types>
tuple<Types...> makeTuple(Types... types)
{
return tuple<Types...>();
}
//I'm using these two functions just to show
//that non constexpr functions can be used to determine type
int generateInt()
{
return 1;
}
char generateChar()
{
return 'a';
}
struct A
{
decltype(makeTuple(generateInt(), generateChar())) t;
A() : t(makeTuple(1, 'a'))
{
}
};
int main()
{
A a;
return 0;
}

Return different types with different template parameter value (but same type)

What I want to do is to define 3 functions like these:
template<int t = 0> int test() { return 8; }
template<int t = 1> float test() { return 8.8; }
template<int t = 2> std::string test() { return "8.9"; }
int main()
{
int a = test<0>();
float b = test<1>();
std::string c = test<2>();
return 0;
}
They use the same type of template parameter but return different types.
I believe there must be some way to do that (like std::get<>() does it), but I can not find how to do it.
It looks to me like you are after function template specialization. Needing to provide a different implementation for each of the calls fits the bill. There is however one caveat, and it's that a specialization may not alter the signature of the primary template being specialized, only the implementation. This means we cannot do e.g.
template<int t> int test(); // Primary
template<> int test<0>() { return 8; } // OK, signature matches
template<> float test<1>() { return 8.8; } // ERROR
But we are not toasted yet. The signature of the specialization has to match the one that primary will get for a specific argument. So if we make the return type dependent on the template parameter, and resolve to the correct type, we could define our specialization just fine.
template<int t> auto test() -> /* Magic involving t that resolves to int, float, string */;
template<> int test<0>() { return 8; }
template<> float test<1>() { return 8.8; }
template<> std::string test<2>() { return "8.9"; }
Does something like that exist? Yes, and you hinted at it. We can use std::tuple. It has a std::tuple_element utility that can map an integer to one of a type sequence (the tuple's elements). With a little helper, we can construct our code to work the way you wish:
using types = std::tuple<int, float, std::string>;
template<int t> auto test() -> std::tuple_element_t<t, types>;
template<> int test<0>() { return 8; }
template<> float test<1>() { return 8.8; }
template<> std::string test<2>() { return "8.9"; }
Now every specialization matches the signature the primary would end up with. And so we get an approval from our compiler.
See it live
The #StoryTeller and #formerlyknownas_463035818 have provided a well-explained template specialization way of doing it. Alternatively, one can combine the three functions to one single function using if-constexpr and with a decltype(auto) return in c++17.
#include <iostream>
#include <string>
#include <cstring>
using namespace std::literals;
template<int t>
constexpr decltype(auto) test() noexcept
{
if constexpr (t == 0) return 8;
else if constexpr (t == 1) return 8.8f;
else if constexpr (t == 2) return "8.9"s;
}
(See live online)
You declared the same template 3 times, while you actually want specialisations. As far as I know you cannot specialize on return type directly (*). However, there is nothing that cannot be solved with an additional layer of indirection. You can do something along the line of:
#include <string>
template <int> struct return_type_tag {};
template <> struct return_type_tag<0> { using type = int; };
template <> struct return_type_tag<1> { using type = float; };
template <> struct return_type_tag<2> { using type = std::string; };
template <int x> typename return_type_tag<x>::type test();
template<> int test<0>() { return 8; }
template<> float test<1>() { return 8.8; }
template<> std::string test<2>() { return "8.9"; }
int main()
{
int a = test<0>();
float b = test<1>();
std::string c = test<2>();
return 0;
}
(*) actually you can, with a small trick, see this answer. The only benefit of my approach is that it already worked pre-c++11.

Template function dependent on non-type parameter

Is it somehow possible to define an overloaded template function based on a non-type parameter?
following situation:
template<uint8_t> void SetupMem();
template<> void SetupMem<4>()
{ /* some code */ }
template<> void SetupMem<8>()
{ /* some code */ }
void TemplateCaller()
{
// use the plattform-specific template function at compile-time
SetupMem<sizeof(size_t)>();
}
now is it somehow possible to change the return value of SetupMem based on the non-type parameter?
e.g.:
template<> uint32_t SetupMem<4>(){}
template<> uint64_t SetupMem<8>(){}
So that TemplateCaller() does not explicitly calls SetupMem with the desired template parameter (so avoiding something like: SetupMem<uint64, sizeof(size_t)>();)? Possible solutions upto C++11 are welcome :)
Just use simple function overloading and std::integral_constant:
std::uint32_t SetupMem(std::integral_constant<int, 4>); // (0)
std::uint64_t SetupMem(std::integral_constant<int, 8>); // (1)
void TemplateCaller()
{
auto a = SetupMem(std::integral_constant<int, 4>{}); // calls (0)
auto b = SetupMem(std::integral_constant<int, 8>{}); // calls (1)
}
You can introduce a template type alias for readability:
template <int X>
using ic = std::integral_constant<int, X>;
std::uint32_t SetupMem(ic<4>);
std::uint64_t SetupMem(ic<8>);
void TemplateCaller()
{
auto a = SetupMem(ic<4>{});
auto b = SetupMem(ic<8>{});
}
live example on wandbox.org
If your compiler doesn't support integral_constant, all you need to do is define it yourself:
template <int>
struct ic { };
std::uint32_t SetupMem(ic<4>);
std::uint64_t SetupMem(ic<8>);
void TemplateCaller()
{
auto a = SetupMem(ic<4>{});
auto b = SetupMem(ic<8>{});
}
live example on wandbox.org
You can write a type trait:
template<::std::size_t x_Size> class
t_IntegralFromSize;
template<> class
t_IntegralFromSize<4> final
{
public: using type = ::std::uint32_t;
};
template<> class
t_IntegralFromSize<8> final
{
public: using type = ::std::uint64_t;
};
template<::std::size_t x_Size> typename t_IntegralFromSize<x_Size>::type
SetupMem();
template<> t_IntegralFromSize<4>::type
SetupMem<4>()
{ /* some code */ }
template<> t_IntegralFromSize<8>::type
SetupMem<8>()
{ /* some code */ }
void TemplateCaller()
{
// use the plattform-specific template function at compile-time
SetupMem<sizeof(size_t)>(); // works without changes
}
online compiler

C++ Variadic Template Remove Function Logic

I've been able to progress further with my variadic template from my previous question. I've now got a new question. In this code example:
#include <iostream>
#include <cstddef>
constexpr std::uint32_t Flag0 = 0x0001;
constexpr std::uint32_t Flag1 = 0x0002;
constexpr std::uint32_t Flag2 = 0x0004;
constexpr std::uint32_t FlagAll = 0xFFFF;
template<std::uint32_t...Cs>
struct flags_tag {constexpr flags_tag(){}; };
template<std::uint32_t...Cs>
struct make_flags{ using type=flags_tag<Cs...>; };
template<std::uint32_t...Cs>
using make_flags_t=typename make_flags<Cs...>::type;
template<std::uint32_t value>
class pValue_t
{
template<std::uint32_t StateMask, class flags>
friend class Compound;
};
template<> class pValue_t<Flag0>
{
public:
pValue_t() :
m_pValue0(reinterpret_cast<void*>(0xFFFFFFFF))
{}
protected:
void* m_pValue0;
};
template<> class pValue_t<Flag1>
{
public:
pValue_t() :
m_pValue1(reinterpret_cast<void*>(0xDEADBEEF))
{}
protected:
void* m_pValue1;
};
template<> class pValue_t<Flag2>
{
public:
pValue_t() :
m_pValue2(reinterpret_cast<void*>(0xCAFEBABE))
{}
protected:
void* m_pValue2;
};
template<std::uint32_t StateMask, class flags>
class Compound;
template<std::uint32_t StateMask, std::uint32_t...Cs>
class Compound< StateMask, flags_tag<Cs...> >:
public pValue_t<Cs>...
{
public:
void print()
{
if (IsStateValid(Flag0))
{
std::cout << this->m_pValue0 << '\n';
}
if ((StateMask & Flag1) == Flag1)
{
std::cout << this->m_pValue1 << '\n';
}
// *** THIS IS THE PROBLEM STATEMENT ***
if (IsStateValid(Flag2))
{
std::cout << this->m_pValue2 << '\n';
}
}
static bool IsStateValid(std::uint32_t stateMask)
{ return ((StateMask & stateMask) == stateMask); }
uint32_t m_stateMask;
};
using my_type = Compound< Flag0 | Flag1, make_flags_t<Flag0, Flag1>>;
int main() {
my_type test;
test.print();
}
the print function contains a reference to m_pValue2, which is valid when the StateMask contains Flag2.
Now, the compiler is warning that it cannot find m_pValue2. I would like for the compiler to remove the chunk of code that references m_pValue2 when the StateMask (known at compile time) does not contain Flag2 (when IsStateValid() is false).
The exact error is as follows:
main.cpp: In instantiation of 'void Compound<StateMask, flags_tag<Cs ...> >::print() [with unsigned int StateMask = 3u; unsigned int ...Cs = {1u, 2u}]':
main.cpp:95:18: required from here
main.cpp:80:27: error: 'class Compound<3u, flags_tag<1u, 2u> >' has no member named 'm_pValue2'
std::cout << this->m_pValue2 << '\n';
I'm hoping this is possible. In other template programming, I've used IsStateValid() to compile out code segments that don't match the StateMask. I've never tried to compile away a possibly missing member variable, however.
Does anyone have any ideas?
Why it doesn't work
All branches in a function template will be compiled regardless of type. It doesn't matter that IsStateValid(Flag2) would be false at compile time, the body of that if must be valid code. As there is no this->m_pValue2 in that case, this is a hard error.
What can you do to fix it
You need to forward each print flag function to a function template that will either print the value (if it exists) or do nothing (if it doesn't). We can use function overloading to help here, and ensure that the entire function will not be instantiated if there is no such flag. For example:
void print()
{
printImpl<Flag0>();
printImpl<Flag1>();
printImpl<Flag2>();
}
template <uint32_t F>
void printImpl() {
printImpl<F>(std::is_base_of<pValue_t<F>, Compound>{});
}
template <uint32_t F>
void printImpl(std::true_type ) {
// we DO have this flag
pValue_t<F>::print();
}
template <uint32_t F>
void printImpl(std::false_type ) {
// we do NOT have this flag
// so do nothing
}
All you need to do at this point is add the appropriate print()s. e.g.:
template<> class pValue_t<Flag2>
{
public:
pValue_t() :
m_pValue2(reinterpret_cast<void*>(0xCAFEBABE))
{}
void print() {
std::cout << m_pValue2 << '\n';
}
protected:
void* m_pValue2;
};
I got this to work (working example), but it seems very hacky. It shows that it's possible - hopefully a more experienced person than I can clean it up.
The idea is to make IsStataValid a constexpr and separate the code in question out into another function, which has two variants. The variant that gets instantiated depends on the compile-time flag:
static constexpr bool IsStateValid(std::uint32_t stateMask)
{ return ((StateMask & stateMask) == stateMask); }
template <typename A = void,
typename T = typename std::enable_if<IsStateValid(Flag2), A>::type>
void blub(int x=0) {
std::cout << this->m_pValue2 << '\n';
}
template <typename A = void,
typename T = typename std::enable_if<!IsStateValid(Flag2), A>::type>
void blub(long x=0) {
}
Then instead of the if statement in print() you call the helper function:
blub();
typename A is a dummy parameter to make the enable_if dependent on a template parameter so SFINAE can kick in. The blubs take a first parameter of a different type so the compiler doesn't complain about it not being able to be overloaded.