Since the function template in the following code is a member of a class template, it can't be specialized without specializing the enclosing class.
But if the compiler's full optimizations are on (assume Visual Studio 2010), will the if-else-statement in the following code get optimized out? And if it does, wouldn't it mean that for all practical purposes this IS a function template specialization without any performance cost?
template<typename T>
struct Holder
{
T data;
template<int Number>
void saveReciprocalOf();
};
template<typename T>
template<int Number>
void Holder<T>::saveReciprocalOf()
{
//Will this if-else-statement get completely optimized out
if(Number == 0) data = (T)0;
else data = (T)1 / Number;
}
//-----------------------------------
void main()
{
Holder<float> holder;
holder.saveReciprocalOf<2>();
cout << holder.data << endl;
}
Chances are it will be optimized. But if you want to be sure you can use a compile-time if by using templates, e.g. Boost’s MPL if_ implementation.
Or you can use SFINAE (Boost.enable_if).
Usually the way to solve this kind of problem is through overloading
template<typename T>
struct Outer {
template<int I>
void inner() {
inner(int_<I>());
}
private:
template<int I>
struct int_ { };
void inner(int_<0>) {
// for I == 0
}
template<int I>
void inner(int_<I>) {
// for others...
}
};
This mimics explicit specializations quite well, and even works in cases where type check for the other paths would go mad (unlike the if solution)
// ...
template<int I>
void inner(int_<I>) {
int tmp[I];
}
// ...
That works because this path is only taken if I != 0. Now in your case, i first of all wonder why you don't just pass a normal function argument. You don't seem to need the compile time nature of I.
// works just fine too in your example
template<typename T>
void Holder<T>::saveReciprocalOf(int Number)
{
// Will this if-else-statement get completely optimized out
if(Number == 0) data = (T)0;
else data = (T)1 / Number;
}
This also has good chances of being optimized if the compiler inlines the function call. Using the template non-type parameter where it's not strictly necessary only limits the abilities of that function not to work with runtime values.
Thanks. Since I want to be certain the conditional is optimized out (because it needs to called very often deep inside loops and I use a switch-case outside the loops to pick the correct path), I'll probably end up using enable_if_c something like in the following code:
using boost::enable_if_c;
template<typename T>
struct Dummy
{
template<int N>
typename enable_if_c<N==2,bool>::type isPrimary() {return true;}
template<int N>
typename enable_if_c<N==3,bool>::type isPrimary() {return true;}
template<int N>
typename enable_if_c<N==5,bool>::type isPrimary() {return true;}
template<int N>
typename enable_if_c<N!=2&&N!=3&&N!=5,bool>::type isPrimary() {return false;}
};
To me this seems a bit less cluttered than the suggestion by Johannes. Although the last (default) case can get quite ugly.
Related
I'd like to write something like that :
template<int i> void f() {}
for (constexpr int i : {1,2,3})
{
f<i>();
}
Is it possible to iterate on constexpr ?
Thank you
As you probably understand, you cannot do the like of:
for (constexpr int i : {1,2,3})
{
f<i>();
}
because, if i is to vary from 1 through 3 in a loop, then it is a variable and
not a compiletime constant. And a variable cannot be a template argument,
as in f<i>: only a compiletime constant can be a template argument.
In C++11 and later, thanks to variadic templates,
you can effectively iterate over an arbitary sequence of compiletime constants
by using compiletime recursion of a template function that accepts a suitable arbitrary sequence
of template arguments.
That will hardly mean anything to you if you don't already know how to do it.
Here is a C++11 example that does what you want to express:
#include <type_traits>
#include <iostream>
template<int i> void f()
{
std::cout << i << '\n';
}
// This overload is chosen when there is only 1 template argument.
template<int First, int ...Rest>
typename std::enable_if<sizeof...(Rest) == 0>::type
for_each_f()
{
f<First>();
}
// This overload is chosen when there is > 1 template argument.
template<int First, int ...Rest>
typename std::enable_if<sizeof...(Rest) != 0>::type
for_each_f()
{
f<First>();
for_each_f<Rest...>();
}
int main()
{
for_each_f<2,3,5,7,11>();
return 0;
}
See it live
Besides variadic templates, this technique depends on the very important C++ meta-programming
principle of SFINAE, and on std::enable_if,
which is the tool that the Standard C++ library provides for exploiting SFINAE.
101010's answer demonstrates a more sophisticated and powerful style of
solution that is available in C++14 (and easy enough to implement in C++11
if you write some supporting boilerplate).
No you can't use a for loop to iterate over at compile time. The for control structure in C++ is used for runtime control flow.
However, you could use other compile time facilities. For example in C++ 14 you could achieve what you want in the following manner:
Define a template wrapper class that's gonna call your function.
template<int i>
struct wrapper {
void operator()() const { f<i>(); }
};
Use std::index_sequence to generate compile time indices.
template<template<int> class W, std::size_t... I>
void caller_impl(std::index_sequence<I...>) {
int t[] = { 0, ((void)W<I>()(), 1)... };
(void) t;
}
template<template<int> class W, std::size_t N, typename Indices = std::make_index_sequence<N>>
void call_times() {
caller_impl<W>(Indices());
}
Then call as
int main() {
call_times<wrapper, 42>();
}
Live Demo
If C++14 is not an option you could take a look here of how you could implement std::index_sequence your self.
I want to write a class method that takes a template parameter pack, but zero arguments, and "iterate" over the types:
struct Bar {
template <typename T, typename... Ts>
void foo() {
// something with T that involves Bar's members
foo<Ts...>();
}
};
What is the preferred way to implement this?
You may use the following:
struct Bar {
template <typename... Ts>
void foo() {
int dummy[] = {0 /*Manage case where Ts is empty*/,
(bar<Ts>(), void() /* To avoid overload `operator,` */, 0)...};
(void) dummy; // suppress warning for unused variable.
}
template <typename T>
void bar()
{
// something with T that involves Bar's members
}
};
In C++17, it can be simplified with Folding expression:
struct Bar {
template <typename... Ts>
void foo() {
(static_cast<void>(bar<Ts>()), ...);
}
template <typename T>
void bar()
{
// something with T that involves Bar's members
}
};
template<class...Fs>
void do_in_order(Fs&&...fs) {
int _[]={0, ( std::forward<Fs>(fs)(), void(), 0 )...};
(void)_;
}
hides the syntax required to execute a pack of function objects in left to right order.
Then:
struct Bar {
template <class... Ts>
void foo() {
do_in_order([&]{
using T = Ts;
// code
}...);
}
};
and in a conforming compiler, we will run the // code with T being each type from left to right.
Note that some compilers claiming to be C++11 compilers may fail to compile the above.
The advantage of this technique is that it hides the nasty "expand and evaluate templates" code within a function with a clear name. You write do_in_order once, and it usually suffices for almost every use of that array-expansion trick.
There are a two important reasons to use this kind of esoteric syntax instead of the "more simple" recursive solutions.
First, it makes things easier for the optimizer. Optimizers sometimes give up after a pile of recursive calls.
Second, the sum of the lengths names of the function signatures for the traditional recursive functions grow at O(n^2). If you use helper types, the total length of the names is also O(n^2). Unless you are careful, this can cause compile time, link time, and binary size bloat.
In C++1z there are plans for some "fold" syntax that may make the esoteric parts of the above less esoteric.
I like overloaded functions and using a typelist:
#include <iostream>
#include <typeinfo>
template <typename ...Ts> struct typelist { };
void foo_impl(typelist<> )
{
// we are finished
}
template <typename T, typename ...Ts>
void foo_impl(typelist<T, Ts...> )
{
std::cout << typeid(T).name() << ", ";
foo_impl(typelist<Ts...>{});
}
template <typename ...Ts>
void foo()
{
std::cout << "called with <";
foo_impl(typelist<Ts...>{});
std::cout << ">" << std::endl;
}
int main()
{
foo<int, char, float>();
}
I have a template class for which certain member functions only make sense if the template parameters satisfy certain conditions. Using, for instance, std::enable_if<> I can define them only for these cases, but how can I call them conditionally? Here is a brief example
template<class T> class A
{
typename std::enable_if<std::is_floating_point<T>::value>::type a_member();
void another_member()
{
a_member(); // how to restrict this to allowed cases only?
}
};
Firstly, you can't use SFINAE like that - the template type parameter needs to be on the function, not the class.
A full solution looks like this:
template<class T> class A
{
private:
template <class S>
typename std::enable_if<std::is_floating_point<S>::value>::type a_member() {
std::cout << "Doing something";
}
template <class S>
typename std::enable_if<!std::is_floating_point<S>::value>::type a_member() {
//doing nothing
}
public:
void another_member()
{
a_member<T>();
}
};
int main() {
A<int> AInt;
AInt.another_member();//doesn't print anything
A<float> AFloat;
AFloat.another_member();//prints "Doing something"
}
WARNING: This is a complete, terrible hack that I have not tried that may never work.
Try adding this to the class declaration:
typename std::enable_if<std::is_floating_point<T>, int*>::type a_enabled_p() { return 0;};
void another()
{
if((a_enabled_p()+1)==1)
{
//Not enabled
}
else if((a_enabled_p()+1)==sizeof(int))
{
//Is enabled
}
}
Here's why this horror might work. If they are floating point, the return value of the predicate is an int*. If they are, there is no typedef, and it defaults to int (I hope). When you add 1 to an int*, you are really adding sizeof(int). Adding 1 to an int increments by one. That means that by checking the value of adding one, we know.
Note: Don't use this. It was fun to come up with, but the above answer is MUCH, MUCH
MUCH
Better. Don't use this. Please.
In my template I need to have different code parts based on whether the typename is a fundamental type or not.
Compiling this code gives a C4067 in MSVC (unexpected tokens following preprocessor directive - expected a newline):
template <typename T>
void MyClass<T>::foo()
{
// ... some code here
#if std::is_fundamental<T>::value
if(m_buf[j] < m_buf[idx_min])
idx_min = j;
#else
const ASSortable& curr = dynamic_cast<ASSortable&>(m_buf[j]);
const ASSortable& curr_min = dynamic_cast<ASSortable&>(m_buf[idx_min]);
// error checking removed for simplicity
if(curr.before(curr_min))
idx_min = j;
}
#endif
The template is to work with both primitive and my own (derived from ASSortable) data types and the error is thrown from template instantiation code:
template class MyClass<char>;
Trying to modify the precompiler expression to this didn't work either:
#if std::is_fundamental<T>::value == true
and produces the same exact warning.
Any ideas how to make this code warning-free?
Edit Another thing that comes to mind is to convert this into a run-time check and live with the "constant if expression" warning... Is there really no way to do this elegantly in a single function with no specializations and no extra bloat?
Edit #2 So the way I solved this (which was obvious, but somehow escaped me...) was to define a bool ASSortable::operator<(const ASSortable& _o) const {return this->before(_o);}; which does the job and makes the code clean (once again).
No more ifs or #ifdefs or any similar clutter in my code!
Can't believe I even asked that question as it had such an obvious and simple answer :(
The common pattern to solve that issue is moving the function to a base class that is specialized and abusing inheritance to bring it to your scope:
template <typename T, bool is_fundamental>
struct Foo_impl {
void foo() {
}
};
template <typename T>
struct Foo_impl<T,true>
{
void foo() { // is fundamental version
}
};
template <typename T>
class Foo : public Foo_impl<T, std::is_fundamental_type<T>::value> {
// ...
};
Another approach would be to implement those as private functions in your class and dispatch to them internally from foo based on the trait. This is really simple and a cleaner solution, but fails if one of the two versions of the foo_impl will not compile. In that case you can use, as others have suggested a template member function to resolve, but I would still offer the non-templated foo as the public interface, forwarding to a private foo_impl template. The reason is that the template in there is an implementation detail to hack conditional compilation, not part of the interface. You don't want user code calling that member function with different template arguments than the type of your own class. Borrowing from pmr's answer:
template <typename T>
struct Foo
{
template <typename U = T,
typename std::enable_if<
std::is_fundamental<U>::value, int >::type* _ = 0
>
void foo() {
std::cout << "is fundamental" << std::endl;
}
//...
That solution allows user code like:
Foo<int> f;
f.foo<std::string>();
Which will instantiate a function that you don't need nor want, and will execute the logic that you don't want. Even if users don't try to fool your class, the fact that is a template in the interface might be confusing and make users think that it is possible to call it for different types.
Preproccessor is run at an early stage of compilation, before the compiler analyzes the types and knows the meaning of std::is_fundamental<T>::value, hence it cannot work this way.
Instead, use specialization:
template<bool> void f();
template<> void f<true>() {
if(m_buf[j] < m_buf[idx_min])
idx_min = j;
}
template<> void f<false>() {
const ASSortable& curr = dynamic_cast<ASSortable&>(m_buf[j]);
const ASSortable& curr_min = dynamic_cast<ASSortable&>(m_buf[idx_min]);
// error checking removed for simplicity
if(curr.before(curr_min))
idx_min = j;
}
template <typename T>
void MyClass<T>::foo()
{
// ... some code here
f<std::is_fundamental<T>::value>();
}
EDIT: You're likely to need to make f a member function, however it's not directly possible since MyClass<T> is a non-specialized template. You could make f a global which delegates the call to the correct member of MyClass. However, there is another approach.
Using overloading, this becomes:
void MyClass<T>::f(const true_type&) {
if(m_buf[j] < m_buf[idx_min])
idx_min = j;
}
void MyClass<T>::f(const false_type&) {
const ASSortable& curr = dynamic_cast<ASSortable&>(m_buf[j]);
const ASSortable& curr_min = dynamic_cast<ASSortable&>(m_buf[idx_min]);
// error checking removed for simplicity
if(curr.before(curr_min))
idx_min = j;
}
template <typename T>
void MyClass<T>::foo()
{
// ... some code here
f(std::is_fundamental<T>::type());
}
You are mixing up states of compilation. The preprocessor is run before the actual compiler and has no knowledge of types or templates. It just performs (very) sophisticated text substitution.
There is nothing such as static if1 in current C++, so you have to resort to a different method to enable conditional compilation. For functions I would prefer enable_if.
#include <type_traits>
#include <iostream>
template <typename T>
struct Foo
{
template <typename U = T,
typename std::enable_if<
std::is_fundamental<U>::value, int >::type = 0
>
void foo() {
std::cout << "is fundamental" << std::endl;
}
template <typename U = T,
typename std::enable_if<
!(std::is_fundamental<U>::value), int >::type = 0
>
void foo() {
std::cout << "is not fundamental" << std::endl;
}
};
struct x {};
int main()
{
Foo<int> f; f.foo();
Foo<x> f2; f2.foo();
return 0;
}
1 References:
Video: Static if presented by Alexandrescu in Going Native.
n3322: Walter E. Brown's proposal for static if
n3329: Sutter, Bright and Alexandrescu's proposal for static if
It's pretty much what it says, you can't use :: in preprocessor directives. Actually, the only thing you can use after #if is a constant-expression that is defined before the compile-time. You can find some info here
std::is_fundamental<T>::value == true cannot be used at pre-processing time. I guess you would have to use some SFINAE trick with std::enable_if:
template <typename T>
typename std::enable_if<std::is_fundamental<T>::value, void>::type
MyClass<T>::foo()
{
// ... some code here
if(m_buf[j] < m_buf[idx_min])
idx_min = j;
}
template <typename T>
typename std::enable_if<!std::is_fundamental<T>::value, void>::type
MyClass<T>::foo()
{
// ... some code here
const ASSortable& curr = dynamic_cast<ASSortable&>(m_buf[j]);
const ASSortable& curr_min = dynamic_cast<ASSortable&>(m_buf[idx_min]);
// error checking removed for simplicity
if(curr.before(curr_min))
idx_min = j;
}
Is it possible in C++ to check the type passed into a template function? For example:
template <typename T>
void Foo()
{
if (typeof(SomeClass) == T)
...;
else if (typeof(SomeClass2) == T)
...;
}
Yes, it is...but it probably won't work the way you expect.
template < typename T >
void foo()
{
if (is_same<T, SomeClass>::value) ...;
else if (is_same<T, SomeClass2>::value) ...;
}
You can get is_same from std:: or boost:: depending on your desire/compiler. The former is only in C++0x.
The problem comes with what is in .... If you expect to be able to make some function call specific to those types within foo, you are sadly mistaken. A compiler error will result even though that section of code is never run when you pass in something that doesn't obey that expected interface.
To solve THAT problem you need to do something a bit different. I'd recommend tag dispatching:
struct v1_tag {};
struct v2_tag {};
template < typename T > struct someclass_version_tag;
template < > struct someclass_version_tag<SomeClass> { typedef v1_tag type; };
template < > struct someclass_version_tag<SomeClass2> { typedef v2_tag type; };
void foo(v1_tag) { ... }
void foo(v2_tag) { ... }
template < typename T > void foo()
{
typedef typename someclass_version_tag<T>::type tag;
foo(tag());
}
Note that you will not be suffering any runtime-polymorphism overhead here and with optimizations turned on it should result in the same or even smaller code size AND speed (though you shouldn't be worrying about that anyway until you've run a profiler).
If you want to do something specific based on the type, specialize the template:
template <typename T>
void Foo() { }
template <>
void Foo<SomeClass>() { }
template <>
void Foo<SomeClass2>() { }
// etc.
(You don't actually want to specialize the function template, though; this is for exposition only. You'll either want to overload the template if you can, or delegate to a specialized class template. For more on why and how to avoid specializing function templates, read Herb Sutter's Why Not Specialize Function Templates?)
No, however you can use partial specialization :
template<typename T>
struct Bar { static void foo(); };
template<typename T>
template<> inline void Bar<T>::foo() {
//generic
}
template<> inline void Bar<int>::foo() {
//stuff for int
}
template<> inline void Bar<QString>::foo() {
//QString
}
Edit Yes with type traits, however it's not really needed.
Edit 2 type_traits example.
#include <type_traits>
template<typename T> void foo() {
using std::is_same;
if (is_same<T, T2>::value || is_same<T, T1>::value) {
/* stuff */
}
}
Yes. You will have to use type traits. For example:
#include <boost/type_traits/is_same.hpp>
template <typename T>
void Foo ()
{
if ((boost::is_same<T, SomeClass>::value))
...;
else if ((boost::is_same<T, SomeClass2>::value))
...;
}
Depending on what you are trying to achieve, using template specialization might be much better choice.
Also, you can use enable_if/disable_if to conditionally enable/disable certain functions/methods. Combining this with type traits will allow, for example, using one function for one set of types and another function for another set of types.