In a function within a template class, I'm trying to distinguish between primitive types and others.
In c++ 11 you can do:
if(std::is_fundamental<T>::value)
{
// Treat it as a primitive
}
else
{
//Treat it otherwise
}
Please correct me if I'm wrong and this is not only in c++ 11.
Is there an alternative to this in earlier versions of c++?
You could use Boost's type traits in C++03 like this:
#include <boost/type_traits/is_fundamental.hpp>
...
if(boost::is_fundamental<T>::value)
{
// Treat it as a primitive
}
else
{
//Treat it otherwise
}
I guess this should work for C++98 as well.
With this code you will likly have trouble. If you need to distinguish between different type traits this must be done at compile time, not at run time. Depending on what operations you are performing one of the two branches of your if may not compile. So it is better to forward to an specialized function:
void operation_impl(boost::true_type /*other params*/) {
// Treat it is primitive
}
void operation_impl(boost::false_type /*other params*/) {
// Treat it otherwise
}
template<class T>
void operation(/* params*/) {
operation_impl(boost::is_fundamental<T>::type() /*other params*/);
}
With this implementation technique only the used branch needs to compile (i.e. be correct).
Edit:
Here are some additional informations. The solution to this problem have to do with instanciation of templates. I switch from is_fundamental to is_array to show how operations may fail.
Lets start with the first example:
template <class T>
void fun(T t) {
if(boost::is_array<T>::value)
{
std::cout << "true" << std::endl;
}
else
{
std::cout << "false" << std::endl;
}
}
void f(int i) {
fun(i);
}
It will compile and run and the compiler will see that only one branch of the if statement will be used and will remove the other as unused code.
In my second example I will do someithing in the case I use an array operation:
template<class T>
void fun(T& t) {
if(boost::is_array<T>::value)
{
std::cout << t[0];
}
else
{
std::cout << t;
}
}
void f(int i) {
fun(i);
}
Now it will not compile. The reason is with the int as an template argument t[0]is ill formed. You cant use this runtime statement to distinguish on type properties at compile time which are needed in your code (in this example the property of beeing an array and the use of t[0]).
In the third example we will disitinguish on compile time via function overloading:
template<class T>
void fun_impl(boost::true_type, T& t) {
std::cout << t[0];
}
template<class T>
void fun_impl(boost::false_type, T& t) {
std::cout << t;
}
template<class T>
void fun(T& t) {
fun_impl(typename boost::is_array<T>::type(),t);
}
void f(int i) {
fun(i);
}
Here is_array<T>::type is either true_type or false_type. This result is used as a selector for choosing the right overload of fun_impl at compile time and only the choosen overload is instanziated and compiled.
Normaly such techniques are used to select at comopile time a best implementation which may be only compilable if the types have certain properties.
2nd edit:
This will of course change if static if is part of the language.
Related
I have to use third party SDK which does NOT provide any compile time information about its version.
Let's say v1 of SDK defines the following functions:
bool func1(int);
bool func2(float) {return false; /* not implemented */}
While v2 of the SDK deprecated and removed func1() and properly implemented func2(). I need to make my code to properly compile and work with both versions of SDK. If it's v1, then choose func1(), if not, then use func2().
I've successfully implemented compile time inquiry whether global scope func1() exists:
constexpr bool hasFunc1();
I tried to select appropriate function using tag-dispatching and template specialization. For example:
template <bool THasFunc1>
struct ExecCode;
template<>
struct ExecCode<true>
{
bool getValue() {
return func1(123);
}
}
template<>
struct ExecCode<false>
{
bool getValue() {
return func2(123.567);
}
}
bool getValue() {
return ExecCode<hasFunc1()>::getValue();
}
However, compiler (GCC) still reports an error func1 has not been declared when compiling with v2 of SDK. Why does it even try to compile the non-existing variant? Is there any way to allow the described selection of function from the global scope?
You're running into a problem where you call a undeclared function with arguments not dependent on template parameters. That is deprecated, if still supported by GCC with permissive mode. Essentially compiler tried to add first implementation of getValue() to the template with parameter "false". Possible workarounds are to use single template specification and if constexpr within getValue() or #ifdef.
Your problem could be also solved without tag dispatching.
#include <iostream>
#if !defined(NEW_VERSION)
bool func1(int) { std::cout << "Implemented" << std::endl; return true; }
bool func2(float) { std::cout << "Not implemented" << std::endl; return false; }
#else
bool func2(float) { std::cout << "Implemented" << std::endl; return true; }
#endif
namespace workaround {
struct null_type {};
template<typename T = null_type>
bool func1(int a, T t = T()) { return func2((float) a); }
}
void universal_implementation() {
using namespace workaround;
func1(123);
}
int main() { universal_implementation(); return 0; }
When func1 is declared, workaround::func1(int, workaround::null_type) would have weaker priority than original function.
I'm learning some new concepts about c++ and I'm playing with them.
I wrote some piece of code that really confuses me in terms of how it works.
#include <iostream>
class aid {
public:
using aid_t = std::string;
void setaid(const std::string& s) {
aid_ = s;
}
const aid_t& getaid() const {
return aid_;
}
private:
aid_t aid_;
};
class c {
public:
using c_t = std::string;
void setc(const aid::aid_t& aid_val) {
if (aid_val.size() < 4)
c_ = "yeah";
else
c_ = aid_val + aid_val;
}
const c_t& getc() {
return c_;
}
private:
c_t c_;
};
template<typename ...Columns>
class table : public Columns... {
};
template <typename... Columns>
void f(table<Columns...>& t) {
t.setaid("second");
std::cout << t.getaid() << "\n";
}
void f2(table<aid>& t) {
t.setaid("third");
std::cout << t.getaid() << "\n";
}
int main() {
table<aid, c> tb;
tb.setaid("first");
std::cout << tb.getaid() << " " << "\n";
// f<c>(tb); // (1) doesnt compile, that seem obvious
f<aid>(tb); // (2) works?
f(tb); // (3) works too -- template parameter deduction
// f2(tb); // (4) doesnt work? worked with (2)...
}
The idea here is simple, I have some table with columns. And then I would like to create some functions that require only some set of columns and doesn't care if passed argument has some extra columns.
My confusion is mostly about points (2) and (4) in code... My intuition says it should be the same, why it isn't and (2) compiles and (4) doesn't? Is there any major topic I'm missing and should read up?
Is there a way to achieve this particular functionality?
In the second case, the compiler still deduces the rest of the template parameter pack, so that you get table<aid, c> & as the function parameter. This is different from (4) (table<aid> &).
[temp.arg.explicit]/9:
Template argument deduction can extend the sequence of template arguments corresponding to a template parameter pack, even when the sequence contains explicitly specified template arguments.
I want to write a C++ function that adjusts type of second argument based on the first one. so I have something like this:
enum FtnType { FTN_A, FTN_B, FTN_C };
void bar( FtnType foo, const int arg = 0)
{
switch(foo)
{
case 0:
{
void ftnA(arg);
break;
}
case 1:
{
void ftnB();
break;
}
case 2:
{
void ftnC(arg);
break;
}
}
}
Now for case 0 I want arg to be an integer, for case 1 I don't want to use any argument and for case 3 I want arg type to be float. I know I can cast type within the a case but that seems like a bad programming practice. What should be the best approach to solve this problem?
You are trying to mix a fun combination of compile-time and run-time logic. While you might be able to achieve something through the use of templates, by specifying argument one as a compile-time known value, I am not entirely sure it is advisable.
You ask for a best practice, and honestly I feel that a best practice would be to take a step back and rethink your design. Why do you need your function to work so differently based on parameter 1?
If you were to change the value of parameter 2, such as would be the case with variadic arguments used in classic printf like functions, then you would have a source of error that would be difficult to detect at compile time, and even harder to detect run-time.
You might consider a more compile time friendly approach using variadic templates (though I still recommend rethinking your design):
template <typename F, typename... T>
void bar(F func, T... params) {
func(params...);
}
The good thing about this approach, is that accidentally passing the wrong parameter type, or number of parameters, will cause a compile time error. This approach will require you to know the function to execute outside of bar though.
void test1(int a, double b, char c) {
std::cout << "test1(" << a << ", " << b << ", " << c << ")\n";
}
void test2() {
std::cout << "test2()\n";
}
int main() {
bar(test1, 1, 2.1, 'c');
bar(test2);
return 0;
}
This test code can be found running here: http://ideone.com/vU30qn and outputs:
test1(1, 2.1, c)
test2()
It seems to me that depending on the first argument you want to take different type for the second argument. C++ is a strong typed language, which implies that you need to know the value of the first argument at compile time. This brings us in the template territory (me happy). Another issue is that the second argument needs to be passed by reference if you hope to modify it.
enum class FtnType { ftn_a, ftn_b, ftn_c };
template <FtnType type> struct Modify;
template <> struct Modify<FtnType::ftn_a>
{
static auto modify(int& a)
{
ftnA(a);
}
}
template <> struct Modify<FtnType::ftn_b>
{
static auto modify()
{
ftnB();
}
}
template <> struct Modify<FtnType::ftn_c>
{
static auto modify(float& a)
{
ftnC(a);
}
}
and usage:
int main()
{
int a = 24;
float f = 42.f;
Modify<FtnType::ftn_a>::modify(a);
Modify<FtnType::ftn_b>::modify();
Modify<FtnType::ftn_c>::modify(f);
}
This works by having a struct templated by FtnType and each specialization for FtnType has a different signature static modify function.
not sure i'm understanding your problem right, but would an overload like this work?
void bar (int arg)
{
ftnA(arg);
}
void bar (float arg)
{
ftnC(arg);
}
void bar ()
{
ftnB();
}
enum class FtnType {FTN_A, FTN_B, FTN_C};
void bar(FtnType foo, const int arg = 0) {
[&] {
switch(foo) {
case FtnType::FTN_A:
return ftnA(arg);
case FtnType::FTN_B:
return ftnB();
case FtnType::FTN_C:
return ftnC(static_cast<double>(arg));
}
}();
}
Live example
You dont need all these functions and enum. Just use overloaded functions:
void ftn(int arg)
{
std::cout << "I've got an int!" << std::endl;
// Do stuff which is in ftnA
}
void ftn(float arg)
{
std::cout << "I've got an float!" << std::endl;
// Do stuff which is in ftnC
}
void ftn()
{
std::cout << "I've got nothing! :(" << std::endl;
// Do stuff which is in ftnB
}
and simply call
ftn(5); // Will print 'I've got an integer!'
ftn(5.0f); // Will print 'I've got an float!'
ftn(); // Will print 'I've got nothing! :('
Is it possible to recognize all calling of a certain function in everywhere
function1<T1>(); function1<T4>(); ...
then add a line that calling this following line in a certain place?
function2<T1>(); function2<T4>(); ...
For example,
class X{
template <class T> function1(){ }
template <class T> function2(){ }
}
class A{}
class B{}
class C{}
int main(){
X x;
//vvvv this code (hopefully) will be auto generated (by macro?)
x.function2<A>();
x.function2<B>(); //<--- I don't care about order of A or B
//x.function2<C>(); //<--- this line should not be generated
//^^^^ Only X's function1 should be recognized,
// not other class's functions with the same name.
x.function1<B>();
x.function1<A>();
x.function1<B>(); .... // called in various places in many .cpp
//If it is called in another .cpp, but not here, it should still be recognized
}
Edit
My old code call :-
function2<T>() inside function1<T>()
It costs CPU significantly (I profiled), because function1 have to check whether function2 was called or not every time.
Here is a draft of a near-zero overhead solution that will work only if you are not going to invoke function1() before main():
#include <iostream>
#include <typeinfo>
template <class T>
void function2()
{
std::cout << "function2<" << typeid(T).name() << ">()" << std::endl;
}
bool dummy = true;
template <class T>
struct Func1WasInstantiated
{
struct CallFunc2
{
CallFunc2() { function2<T>(); }
void operator()() const { dummy = false; }
};
static CallFunc2 callFunc2;
};
template <class T>
typename Func1WasInstantiated<T>::CallFunc2 Func1WasInstantiated<T>::callFunc2;
template <class T>
void function1()
{
Func1WasInstantiated<T>::callFunc2();
std::cout << "function1<" << typeid(T).name() << ">()" << std::endl;
}
int main()
{
std::cout << "------- Entered main() ---------" << std::endl;
function1<int>();
function1<double>();
function1<int>();
return 0;
}
Output (check it on IDEONE):
function2<i>()
function2<d>()
------- Entered main() ---------
function1<i>()
function1<d>()
function1<i>()
The global variable dummy is the acceptor of the side effect, that ensures that Func1WasInstantiated<T>::callFunc2 is linked into the program and makes the code work as intended. Without the side effect contained in callFunc2() I can imagine an aggressively optimizing compiler eliminating that line from function1() (that is normal) and letting the linker leave out the callFunc2 objects as they become unreferenced (I cannot judge whether this would be against the C++ standard or not).
I'm using a timer library in Arduino IDE that has a function which takes "void(*func)(void)" as a parameter and runs it after certain time.I need to pass a function in my code with that library, the problem is I need "n" functions that do the same thing (just the variables involved inside the function take different values, which I take from an array of struct), that's why I can't use only one function and I need to be able to compile different functions with identical syntax but different variables involved.
I don't know how I can resolve this, what I want to do is to be able to create functions like in a for loop,
for(int i=0;i<MAX_FUNC;i++)
{
void func[i](){
x= structuredata.x[i];
}
}
I know this syntax is completely wrong but I'd like to know how can I achieve something like this . I tried using classes instead, but the library didn't let me use void functions created in a class as parameters, it indicated "unresolved overloaded function type"
If you're into template overrides and can restructure your functions as such, a solution to packing up a stack of callbacks to be fired consecutively is closer than you may think. You can make this more generic if the consistency of the function is literally identical. I.e. you can do this instead:
#include <iostream>
int ar[5] = { 1,2,3,4,5 };
// your function here
template <int i>
void callback()
{
// your code here. i is provided
int x = ar[i];
std::cout << "Got Value: " << x << '\n';
};
////////////////////////////////////////////////////////////
// unraveller
template<int N>
void callback_set()
{
callback_set<N-1>();
callback<N-1>();
}
// base callback set
template<>
void callback_set<0>() {}
////////////////////////////////////////////////////////////
int main()
{
callback_set<3>();
return 0;
}
Output
Got Value: 1
Got Value: 2
Got Value: 3
You "register" callback_set<N> as your callback, and it will chain up the calls to your function(s) for you. If individualized access to different implementations is needed, you can still to that, using full specializations:
#include <iostream>
// prototypes
template <int i>
void callback() {};
// your functions here
template<>
void callback<0>()
{
std::cout << "Callback #0" << '\n';
}
template<>
void callback<1>()
{
std::cout << "Callback #1" << '\n';
}
template<>
void callback<2>()
{
std::cout << "Callback #2" << '\n';
}
////////////////////////////////////////////////////////////
// unraveller
template<int N>
void callback_set()
{
callback_set<N-1>();
callback<N-1>();
}
// base callback set
template<>
void callback_set<0>() {}
////////////////////////////////////////////////////////////
int main()
{
callback_set<3>();
return 0;
}
Output
Callback #0
Callback #1
Callback #2
In essence you style-up your registered callback using callback_set<N> where N is the number of callbacks you've provided overrides for. Just a thought, but seems like it would be a fairly elegant solution to your problem if I understand it correctly.
You need some metaprogramming for that...
const int MAX_FUNC = 1000;
typedef void (*Tcallback)();
struct Tdata
{
int whatever;
};
Tdata callbackData[MAX_FUNC];
Tcallback callbacks[MAX_FUNC];
template <int index>
void callbackToIndex()
{
// callback knows it's index and thus can access some global structure for it's data
printf("%u", index);
callbackData[index];
}
template <int index>
void callbackCreate()
{
callbacks[index] = &callbackToIndex<index>;
callbackCreate<index - 1>();
}
template <>
void callbackCreate<-1>()
{
}
void create()
{
callbackCreate<MAX_FUNC - 1>();
}