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.
Related
I've encountered the following code from Unreal Engine's source
namespace UE4Asserts_Private
{
// This is used by ensure to generate a bool per instance
// by passing a lambda which will uniquely instantiate the template.
template <typename Type>
bool TrueOnFirstCallOnly(const Type&)
{
static bool bValue = true;
bool Result = bValue;
bValue = false;
return Result;
}
FORCEINLINE bool OptionallyDebugBreakAndPromptForRemoteReturningFalse(bool bBreak, bool bIsEnsure = false)
{
if (bBreak)
{
FPlatformMisc::DebugBreakAndPromptForRemoteReturningFalse(bIsEnsure);
}
return false;
}
}
#define ensure( InExpression ) (LIKELY(!!(InExpression)) || FDebug::OptionallyLogFormattedEnsureMessageReturningFalse(UE4Asserts_Private::TrueOnFirstCallOnly([]{}), #InExpression, __FILE__, __LINE__, TEXT("") ) || UE4Asserts_Private::OptionallyDebugBreakAndPromptForRemoteReturningFalse(UE4Asserts_Private::TrueOnFirstCallOnly([]{}), true))
Now, whenever we use ensure(SomeExpression), the UE4Asserts_Private::TrueFirstCallOnly argument to FDebug::OptionallyLogFormattedEnsureMessageReturningFalse evaluates to true only on the first time it gets called for a particular callstack ( I'm thinking per callstack, as TrueOnFirstCallOnly evaluates to false on the next call to ensure from the same callstack, but triggers the ensure from a different callstack but not very sure ) and I don't understand how this works.
As they state in the comments, Somehow passing the lambda []{} to the template function uniquely instantiates it. How does it work? And what is the lambda passed as a template really unique for, is it the call-stack or something else?
LIKELY(!!(InExpression)) can be just thought to evaluate to true if the expression is true
This is how such a true_on_first_call could be implemented:
include <iostream>
template <typename T> struct true_on_first_call {
static bool first;
bool operator()() {
if (first) {
first = false;
return true;
}
return false;
}
};
template <typename T> bool true_on_first_call<T>::first = true;
template <typename T>
bool get_true_on_first_call(const T &){ return true_on_first_call<T>()(); }
void foo() {
std::cout << get_true_on_first_call([]{}) << "\n"; // instantiation for []{}
}
void bar() {
std::cout << get_true_on_first_call([]{}) << "\n"; // instantiation for []{}
} // note: its a different type
// than the []{} above!
// but the same on
// repeated calls to foo
int main() {
std::cout << "first \n";
foo();
bar();
std::cout << "second \n";
foo();
bar();
}
Live demo
The trick is that each labmda expression has a unique type, hence it will result in a different instantiation of true_on_first_call. Even if the lambdas expressions are the same ( []{} vs []{}) they are of different type. On the other hand, the same lambda expression (ie the one on first call of foo and the one on second call of foo) are of same type. In this way one can get a unique instantiation each time you write get_true_on_first_call([]{}).
This very strange request came up ...
I need to do a compile time check whether the current function has a void return type or not and fail compilation if the return type is void.
I tried to do some magic with http://en.cppreference.com/w/cpp/types/result_of and decltype also, however I just cannot get closer to a solution.
#include <type_traits>
void other_func(void) { }
void test_maxi(void)
{
typedef decltype(&::other_func) TYPE;
static_assert(std::is_same<TYPE, void>::value, "not void");
}
int main() {
}
So here comes the question:
Is it possible to do this for the current function?
EDIT The return type check should go in a macro, since it will be used in several functions.
You can implement compile-time checking if one string literal starts with another, and use the __PRETTY_FUNCTION__ macro, which is set to string literal that starts with function return type. You should check if this macro starts with void followed by space.
This code compiles fine:
constexpr bool startsWith(const char* a, const char* b) {
return *a == *b && (*(a + 1) == '\0' || startsWith(a + 1, b + 1));
}
int f() {
static_assert(!startsWith("void ", __PRETTY_FUNCTION__), "not void");
return 1;
}
int main() {
}
If you change f return type to void:
constexpr bool startsWith(const char* a, const char* b) {
return *a == *b && (*(a + 1) == '\0' || startsWith(a + 1, b + 1));
}
void f() {
static_assert(!startsWith("void ", __PRETTY_FUNCTION__), "not void");
}
int main() {
}
static_assert will fire.
The __PRETTY_FUNCTION__ macro seems to be specific to GNU C++ Compiler, however, clang++ works fine since it defines this macro as well. If you are using another compiler, you should check if this macro is really being set, and if not, read compiler documentation in order to determine similar
macro, e.g., __FUNCSIG__.
You can play around with #ifdef __PRETTY_FUNCTION__ ... to make this more portable between various compilers, but I believe this is a topic for another question.
If you can name the current function then the simplest way is:
static_assert(!std::is_same<decltype(test_maxi()), void>::value, "void");
Try this:
template <typename ... Args>
constexpr bool return_void(void(Args ...)) { return true; }
template <typename R, typename ... Args>
constexpr bool return_void(R(Args ...)) { return false; }
Let's suppose we have the following functions:
void f() {}
void g(int) {}
void h(int*,char&) {}
void i(float,bool) {}
void j(const char *const) {}
void k(void()) {}
int l() { return {}; }
float m(int) { return {}; }
All the calls to return_void will return true as long as it is called with the first six functions, the return_void(l) and return_void(m) call will return false because they will invoke the second version of the template, the one returning false.
Check it online
This will allow you to check if a function return void both at runtime and compile time:
int main() {
static_assert(return_void(f), "not void");
if (!return_void(m))
std::cout << "m result is: " << m(0) << '\n';
return 0;
}
You can check the return type of the current function by checking whether a dead return can compile:
struct ConvertToAnything {
template <class T>
operator T() const { assert(!"Don't call me!"); }
};
#define CHECK_NONVOID_RETURN() if(true); else return ConvertToAnything{}
int f() {
CHECK_NONVOID_RETURN(); // Passes
return 42;
}
void g() {
CHECK_NONVOID_RETURN(); // Fails at compile-time
}
The case of void is a special one, so this is enough. But you can also forbid other types by overloading ConvertToAnything::operator Type() = delete;. Allowing void is a bit more involved, but still feasible.
All you need is to detect the return type and check if it is of type void. To check the type you can use std::is_void. return type can be detected with following template:
#include <type_traits> // for is_void
template<typename R, typename... A>
void test(R (*func)(A...)) {
static_assert(
!std::is_void<R>::value,
"void return type is not allowed"
);
}
// functions to check:
void a(int, char*) {}
int b(char, float) {return 0;}
int main()
{
test(a); // < assert triggered here
test(b);
}
#include <iostream>
template<typename Impl>
struct renderer{
void get(){
static_cast<Impl*>(this)->get();
}
};
struct open_gl : public renderer<open_gl>{
void get(){
std::cout << "OpenGL" << std::endl;
}
};
struct direct_draw : public renderer<direct_draw>{
void get(){
std::cout << "DX" << std::endl;
}
};
template<typename T>
void print_renderer(renderer<T> r){
r.get();
}
int main() {
auto gl = open_gl();
auto dx = direct_draw();
print_renderer(gl);
print_renderer(dx);
}
Why can't I change the parameter of print_renderer to void
print_renderer(const renderer<T> &r)?
cannot convert 'this' pointer from 'const renderer<open_gl>' to 'renderer<open_gl> &'
`
Why do I get a runtime error when I rename the method get in open_gl from
get to get1? Shouldn't this trigger a compiler error? Error = Stack overflow
**Note I am using the latest MSVC
1) Because get is not a const member function : it cannot make the promise of not modify your (const) argument.
You could declare get as const, and it compiles fine :
void get() const { ... }
2) The base get method will be called, going into infinite recursion : Stack Overflow.
If you declare your function override (it needs to be virtual), the compiler will throw an error if it does not indeed override a base method :
void get1() override { ... } // Compiler error
void get() override { ... } // Ok
Note:
The title is "Static polymorphism in C++", but I think that you misunderstood what is static polymorphism : it does not (have to) make use of inheritance (as you did). Rather, the templates compile-time duck typing will statically "resolve" function calls for you.
That is, you don't need related types, you don't need the base renderer class at all, and you can simply do the following (in which case, renaming to get1 will cause a compiler error) :
#include <iostream>
struct open_gl {
void get(){
std::cout << "OpenGL" << std::endl;
}
};
struct direct_draw {
void get(){
std::cout << "DX" << std::endl;
}
};
template<typename T>
void print_renderer(T r){
r.get();
}
int main() {
auto gl = open_gl();
auto dx = direct_draw();
print_renderer(gl);
print_renderer(dx);
}
Live demo
Becuase get is not marked const.
Because the base class method is used (irrelevantly of cast), and it goes into infinite loop.
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>();
}
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.