I would like to conditionally declare a local variable in a function, based on a template bool parameter. So if it is true it should be there, otherwise shouldn't be there in the sense that I don't want that variable to allocate memory on the stack or call its constructor. It could also be a basic type.
I cannot declare it within the constexpr if block because I need persistence between the usages.
I can just declare the variable and add [[maybe_unused]]. Then, is there a compiler optimization which guaranties not to allocate memory for the variable?
template <bool T> void foo()
{
[[maybe_unused]] SomeLargeClass x;
if constexpr(T)
{
... do something with x
}
... do something without x
if constexpr(T)
{
... do something more with x
}
}
I tried to replace the declaration with
std::enable_if_t<T, SomeLargeClass> x;
but it doesn't work because the T==false case fails to provide a type. Why is this not SFINAE?
Do I have any other options?
As-if rule might discard unused SomeLargeClass, but it is more complicated if that class do allocations.
One easy trade-of is to use std::conditional and have SomeLargeClass when needed, and some dummy small class in other case;
struct Dummy
{
// To be compatible with possible constructor of SomeLargeClass
template <typename ...Ts> Dummy(Ts&&...) {}
};
template <bool B> void foo()
{
[[maybe_unused]] std::conditional_t<B, SomeLargeClass, Dummy> x;
if constexpr(B) {
// ... do something with x
}
// ... do something without x
if constexpr(B) {
// ... do something more with x
}
}
Yes, compilers can optimize unused variables, supposed it can proove that construction and destruction has no observable side effects.
It is not SFINAE, because not a type x; makes the whole function fail. There is no alternative foo, hence it is a hard error.
Yes, you can specialize foo:
.
struct SomeLargeClass {};
template <bool T> void foo();
template <> void foo<false>() {
//... do something without x
}
template <> void foo<true>() {
SomeLargeClass x;
//... do something with x
foo<false>();
//... do something more with x
}
You could use the local variable x, but give it a specialized type:
#include <iostream>
using std::ostream;
template <bool T> struct MaybeLargeType;
template <> struct MaybeLargeType<true> { int bigone; };
template <> struct MaybeLargeType<false> {};
ostream& operator<<(ostream& s, const MaybeLargeType<true>& o) { return s << o.bigone; }
ostream& operator<<(ostream& s, const MaybeLargeType<false>& o) { return s << "nope"; }
template <bool T> void foo() {
MaybeLargeType<T> x;
if constexpr(T) {
x.bigone = 1;
}
// other stuff
if constexpr(T) {
x.bigone += 3;
}
std::cout << x;
}
int main()
{
foo<true>();
foo<false>();
return 0;
}
This moves the LargeType inside variable x, which is big-or-small depending on the template parameter, so your code in the if constexpr blocks is slightly more wordy.
Just a variant of the specialisation approach:
template <bool B>
class C
{
public:
void step1() { };
void step2() { };
};
template <>
class C<true>
{
public:
void step1() { /* use the large data*/ };
void step2() { /* use the large data*/ };
private:
// large data
};
template <bool B>
void foo()
{
C<B> x;
x.step1();
// x-unaware code
x.step2();
}
Which one looks better? Just a pure matter of taste...
I'll leave finding better names to you.
If your class has a trivial constructor, just don't worry - the compiler will not allocate an unused object on stack.
If your class has a constructor which does some work, you might want to skip this work if you know it's wasted. The compiler might still notice that the object is unused, and skip the constructor. Check this before you do any changes to your code (premature optimization)!
But if the constructor has some side-effects (not recommended), you have to help the compiler. One way to do it is by using unique_ptr:
template <bool T> void foo()
{
unique_ptr<SomeLargeClass> x;
if constexpr(T)
{
... allocate x
... do something with *x
}
... do something without x
if constexpr(T)
{
... do something more with *x
}
}
Related
Is it possible to make a certain template function have 2 accessibility level for some certain template parameter? (via splitting into 2 functions?)
class B{
enum ENU{
T0,T1,T2
}
template<ENU T=T0> someType f(){ ... } //want T1,T2 = public, T0 = private
};
Current usage (the solution should not change it):-
B b;
int aa=b.f<T0>(); //should fail
std::string bb=b.f<T1>();// should ok
Edit: B has a lot of functions like this.
Here is the full code (just in case someone want to edit or use) https://ideone.com/ryNCml.
I doubt what you are trying to do is possible, as specializing functions on a value ain't allowed in C++.
Though if you don't need enumerations, you could write something similar:
class B {
public:
struct T0{};
struct T1{};
struct T2{};
template<typename T> void f(T, ...) {
static_assert(std::is_same_v<T, T1> || std::is_same_v<T, T2>);
}
private:
void f(T0, ...) {}
};
int main(int argc, char **argv) {
B b{};
b.f(T1{}); // Should compile
b.f(T0{}); // Should not compile
}
If you would use the same function implementation, you can either forward this to a common method, or simply put T0 private.
Alternatively, you could make use of a proxy object which could convert the value, though I'm not sure if this is standard C++ of an extension of the compiler I'm familiar with:
class B {
public:
enum class T { //< Strong typed!
T0,
T1,
T2
}
template <T t>
struct TWrapper {};
template <T ActualT>
void f(..., TWrapper<ActualT> tw = TWrapper<ActualT>{});
private:
template <>
struct TWrapper<T0> {};
}
As far as I can understand, you want to forbid the use of T0 as a template parameter while invoking member method f.
To do that, you can use either std::enable_if or a static_assert.
It follows a minimal, working example:
#include<type_traits>
class B {
public:
enum ENU { T0,T1,T2 };
template<ENU T>
std::enable_if_t<(T==T1||T==T2),int>
f() { return 42; }
template<ENU T>
int g(){
static_assert(T==T1||T==T2, "not allowed");
return 42;
}
};
int main() {
B b;
b.f<B::T1>();
// It doesn't work
//b.f<B::T0>();
b.g<B::T1>();
// It doesn't work
//b.g<B::T0>();
}
Given you want to support only a finite set of template arguments, I would write three functions which are not template functions, and give them the right visibility. Then make them delegate to a private template function which does the work. This would look like:
class B{
public:
enum ENU{
T0,T1,T2
}
private:
template<ENU T=T0> int f(){
std::cout<<"In enum "<<T<<std::endl;
return 0;
}
protected:
someType fT0() { return f<T0>(); }
public:
someType fT1() { return f<T1>(); }
someType fT2() { return f<T2>(); }
};
Contrary to your requirements, the usage changes - but this is often the simplest approach:
B b;
int aa=b.fT0(); // fails
int bb=b.fT1();// ok
Alternatively, you can make the template be public, but give it a dummy argument (with a default), and make the type of the dummy argument depend on the template parameter (via traits). If the type of the dummy is a private class, the template will only be callable by a member.
template <ENU T>
struct protection_traits;
class B{
friend class protection_traits<T0>; // So it has access to Protected.
protected:
struct Protected{};
public:
struct Public{};
enum ENU{
T0,T1,T2
}
template<ENU T=T0> int f( typename protection_traits<T>::type = {})
{ std::cout<<"In enum "<<T<<std::endl; }
};
template <ENU T>
struct protection_traits
{
typedef B::Public type; // Default to public
};
template<>
struct protection_traits<T0>
{
typedef B::Protected type; // But T0 uses Protected
};
Usage:
B b;
int aa=b.f<T0>(); // fails (no access to B::Protected)
int bb=b.f<T1>(); // ok
Note: This latter solution hasn't been fed to a compiler. There will be typos.
Here is a simple example which illustrates the issue:
// this class requires a parameter to its constructor
class A
{
A() = delete;
A(int x) {}
};
using B = A;
using C = A;
using Vector = boost::fusion::vector<A, B, C>;
// somewhere else in my code
template <typename FusionVector>
void fun()
{
// I need to instantiate this vector here, and initialise each element with some integer.
// I _know_ what parameters the types take, but I have no idea what types they are
// or how many of them there are. Can I do this?
FusionVector vec; // this won't work...
}
int main()
{
int x = 10; // I want to construct all types in Vector with this value
fun<Vector>(); // how do I do that?
}
Like the commenters said, the question arises where you'll get the values from. Now, I assumed you mean you know what values to pass for "default" construction (even though there is not, technically, a default constructor).
For this purpose, you can use a trait:
namespace mytraits {
template <typename T>
struct elem_construct {
static T call() { return T(); }
};
}
As you can see, the default implementation of elem_construct::call just calls the default constructor [1].
Now, how to invoke this trait for each vector element?
In a perfect world (read: where Boost Fusion was using variadics in true C++11 style), it would be simple
template <typename FusionVector> struct fun_helper;
template <typename... Ts>
struct fun_helper<boost::fusion::vector<Ts...> > {
static typename boost::fusion::vector<Ts...> call() {
return { std::move(mytraits::elem_construct<Ts>::call())... };
}
};
However, this fails on the reason that Boost Fusion supports C++03 and there are no true variadics. Therefore, 10 [2] template arguments are deduced, and we would end up passing 3 A instances as well as 7 instances of type boost::fusion::void_... Yeah. That doesn't really work.
So jumping through some hoops to placate the compiler:
namespace detail {
template <typename... Ts>
struct internal_fun_helper {
static typename boost::fusion::vector<Ts...> call() {
return boost::fusion::vector<Ts...> (std::move(mytraits::elem_construct<Ts>::call())...);
}
};
// helpers that detect the real cardinality of vectors even in the presence of C++03 faux variadics
// {{{ plumbing
template <typename FusionVector> struct fun_helper;
template <typename T1>
struct fun_helper<boost::fusion::vector<T1> > {
static typename boost::fusion::vector<T1> call() { return internal_fun_helper<T1>::call(); }
};
template <typename T1, typename T2>
struct fun_helper<boost::fusion::vector<T1,T2> > {
static typename boost::fusion::vector<T1,T2> call() { return internal_fun_helper<T1,T2>::call(); }
};
// etc. - you get the idea
Now you can just dispatch the specializations using fun:
template <typename FusionVector> FusionVector fun() {
return detail::fun_helper<FusionVector>::call();
}
And it all works, see this demo Live On Coliru
// here's the magic that tells our `fun` factory how to construct A
namespace mytraits {
template <>
struct elem_construct<A> { static A call() { return A(42); } };
}
#include <boost/phoenix.hpp>
using boost::phoenix::arg_names::arg1;
int main()
{
boost::fusion::for_each(fun<boost::fusion::vector<A, B, C>>(), std::cout << arg1 << "\n");
}
Printing out
A[42]
A[42]
A[42]
[1] (or value initializes T for primitive types and aggregates).
[2] depending on preprocessor defines, but 10 is the default limit (see FUSION_MAX_VECTOR_SIZE)
I only have an hpp file for a school assignment in C++ (I am not allowed to add a cpp file, declaration and implementation should be both written in the file).
I wrote this code inside it:
template<class T>
class Matrix
{
void foo()
{
//do something for a T variable.
}
};
I would like to add another foo method, but this foo() will be specialized for only an <int>.
I have read in some places that I need to declare a new specialization class for this to work. But what I want is that the specialized foo will lie just beneath the original foo, so it will look like this:
template<class T>
class Matrix
{
void foo(T x)
{
//do something for a T variable.
}
template<> void foo<int>(int x)
{
//do something for an int variable.
}
};
Why am I getting an error for this syntax ("expected unqualified-id before '<' token")?
Why isn't this possible?
How can I fix this without declaring a new specialized class?
Thanks
foo isn't a template. It's a member function of a template. Thus foo<int> is meaningless. (Also, explicit specializations must be declared at namespace scope.)
You can explicitly specialize a member function of a particular implicit instantiation of a class template:
template<class T>
class Matrix
{
void foo(T x)
{
//do something for a T variable.
}
};
// must mark this inline to avoid ODR violations
// when it's defined in a header
template<> inline void Matrix<int>::foo(int x)
{
//do something for an int variable.
}
You need to define the original foo method as a template, and actually there is no need for your class to be a template, only the method:
class Matrix
{
template<typename T> void foo(T x)
{
//do something for a T variable.
}
template<> void foo<int>(int x)
{
//do something for an int variable.
}
};
UPDATE: The code works only in Visual Studio. Here is a code that should work elsewhere too:
class Matrix
{
template<typename T> void foo(T x)
{
//do something for a T variable.
}
};
template<> void Matrix::foo<int>(int x)
{
//do something for an int variable.
}
I have a big data member for a class, which is only used for testing:
template <bool testing>
class foo {
int testbuf[1000];
}
How can I make it so? Only when testing is true, include testbuf[]?
Specialize:
template <bool> class foo { };
template <> class foo<true>
{
// everything needed for testing
};
Update: To clarify some points raised in the comments: You would write one such "testing" template per individual item that you want to specialize, so that there's no code duplication. Imagine your real class template is actually bar:
template <bool Testing>
class bar
: private foo<Testing> // specializable base
{
// common stuff
Widget<Testing> widget; // specializable member
Gadget gadget; // unconditional member
};
You can also use composition rather than inheritance; whichever fits best. If you go with inheritance, make sure to spell out this->testbuf.
you can use ifdef stuff
#define DEBUG_MODE
class Foo{
#ifdef DEBUG_MODE
int testbuf[1000];
#else
int testbuf[10];
#endif
}
template <bool testing>
class foo {
}
and
template <>
class foo <true>{
int testbuf[1000];
}
I will assume that testing isn't just used to hold that buff.
template <bool testing>
struct foobuf
{};
template <>
struct foobuf<true>
{
enum {testbuf_size = 1000};
int testbuf[testbuf_size];
foobuf() { std::fill_n( &testbuff[0], testbuf_size, int() ); }
};
template <bool testing>
class foo : public foobuf<testing> {
// ...
};
Going a bit further, you could include a dotest function in foobuf that works like this:
template<bool>
struct foobuf
{
template<typename Func>
void doTest( Func const& unused );
};
template<>
struct foobuf<true>
{
enum {testbuf_size = 1000};
int testbuf[testbuf_size];
foobuf() { std::fill_n( &testbuf[0], testbuf_size, int() ); }
template<typename Func>
void doTest( Func const& f )
{
f( testbuf, testbuf_size );
}
};
which you would use like this within foo:
void foo::some_function(...)
{
// some code
doTest( [&]( int* buf, size_t length )
{
// the code in here only runs if we test was true in foo
// and if so, it has access to the test buff via the buf* parameter
// oh, and it will be almost certainly inlined if test was true in foo
// and thrown away and never created if it was false.
});
}
but that is just me.
I have a template class, say:
template<class T>
class someClient
{
void someCallbackA() {foo_->onA();}
void someCallbackB() {foo_->onB();}
private:
T* foo_;
};
which I can instantiate with a bunch of different types T which support the onA and onB interface. I happen to have a case where two out of the several different types T I use needs a particular behavior controlled from someClient so I need to add some function doBar() to these two types (call them Edge1 and Edge2). Then I want a part of the someClient code to call foo_->doBar() but without breaking when the type of foo_ does not have that. Is there a way to use boost::enable_if to have a someClient::doBar() which will call foo_->doBar() only for those two types, but not be there, or expand to nothing if the types are not Edge1 or Edge2?
I was thinking along the lines of:
template <class T, enable_if<mpl_or<is_same<T,Edge1>, is_same<T,Edge2> > >
someClient<T>::doBar() {foo_->doBar();}
You don't need to pull any special tricks at all if you just don't call member functions that don't make sense. Template member functions are only specialized when needed (unless you add an explicit specialization). So the following code works fine:
template <typename T> struct Foo
{
void do_foo() { p->foo(); }
void do_bar() { p->bar(); }
T * p;
};
struct A { void foo() {} };
int main()
{
A a;
Foo<A> x = { &a };
x.do_foo();
}
The fact that Foo<A>::do_bar wouldn't compile is not an issue, since the member function is never instantiated. And p->bar isn't a compiler error, because p has a dependent type and the line is thus only parsed in the second lookup phase (which never happens).
I think this does what you want. I used C++11 <type_traits> instead of boost's:
struct Edge {
void doBar() { std::cout << "did Bar."; }
};
template<typename T>
class someClient
{
public:
template<typename U = T>
typename
std::enable_if<std::is_same<U, Edge>::value, void>::type
doBar() { foo_->doBar(); }
template<typename U = T>
void doBar( typename std::enable_if<!std::is_same<U, Edge>::value, void>::type* = 0 )
{ /* do nothing */ }
private:
T* foo_;
};
int main()
{
someClient<int> i;
someClient<Edge> e;
i.doBar();
e.doBar(); // outputs "did Bar."
}
doBar() needs to be template itself for this to work, explanation here: std::enable_if to conditionally compile a member function