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.
Related
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
}
}
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.
I don't have a lot of experience with templates but I am wondering if the following scenario is possible. Assume we have a class S with static member stat. I can get it to dynamically generate different code using typeid as:
template <class S>
void foo()
{
if (typeid(S::stat) == typeid(AType))
implementation 1;
else
implementation 2;
}
But since all information is known at compile time is it possible to create a specialization of foo for S::stat being of type Atype?
You're probably looking to do something like this:
template<typename T> class foo_impl {
public:
static void foo()
{
// This is your implementation 2
}
};
template<> class foo_impl<AType> {
public:
static void foo()
{
// This is your implementation 1
}
};
template <class S>
void foo()
{
foo_impl<typename S::Stat>::foo();
}
One common way of solving this problem is through tag dispatching. We can, at compile time, produce different types for whether or not S::stat matches AType - and use those types to call different overloads:
template <class S>
void foo() {
foo_impl(std::is_same<decltype(S::stat), AType>{});
}
void foo_impl(std::true_type /* S::stat matches AType */) {
// implementation 1
}
void foo_impl(std::false_type /* S::stat doesn't match AType */) {
// implementation 2
}
I was not able to utilize the decltype solution because my compiler does not support it.
I was able to utilize the foo_impl class solution but only when I declare MyClass as:
class MyClass {
public:
typedef AType Stat;
static const Stat stat = VAL;
...
}
Consider the following code :
template<bool AddMembers> class MyClass
{
public:
void myFunction();
template<class = typename std::enable_if<AddMembers>::type> void addedFunction();
protected:
double myVariable;
/* SOMETHING */ addedVariable;
};
In this code, the template parameter AddMembers allow to add a function to the class when it's true. To do that, we use an std::enable_if.
My question is : is the same possible (maybe with a trick) for data members variable ? (in a such way that MyClass<false> will have 1 data member (myVariable) and MyClass<true> will have 2 data members (myVariable and addedVariable) ?
A conditional base class may be used:
struct BaseWithVariable { int addedVariable; };
struct BaseWithoutVariable { };
template <bool AddMembers> class MyClass
: std::conditional<AddMembers, BaseWithVariable, BaseWithoutVariable>::type
{
// etc.
};
First off, your code just won't compile for MyClass<false>. The enable_if trait is useful for deduced arguments, not for class template arguments.
Second, here's how you could control members:
template <bool> struct Members { };
template <> struct Members<true> { int x; };
template <bool B> struct Foo : Members<B>
{
double y;
};
I'm looking for a better way to this. I have a chunk of code that needs to handle several different objects that contain different types. The structure that I have looks like this:
class Base
{
// some generic methods
}
template <typename T> class TypedBase : public Base
{
// common code with template specialization
private:
std::map<int,T> mapContainingSomeDataOfTypeT;
}
template <> class TypedBase<std::string> : public Base
{
// common code with template specialization
public:
void set( std::string ); // functions not needed for other types
std::string get();
private:
std::map<int,std::string> mapContainingSomeDataOfTypeT;
// some data not needed for other types
}
Now I need to add some additional functionality that only applies to one of the derivative classes. Specifically the std::string derivation, but the type doesn't actually matter. The class is big enough that I would prefer not copy the whole thing simply to specialize a small part of it. I need to add a couple of functions (and accessor and modifier) and modify the body of several of the other functions. Is there a better way to accomplish this?
Impose another level of indirection in the template definitions:
class Base
{
// Generic, non-type-specific code
};
template <typename T> class TypedRealBase : public Base
{
// common code for template
};
template <typename T> class TypedBase : public TypedRealBase<T>
{
// Inherit all the template functionality from TypedRealBase
// nothing more needed here
};
template <> class TypedBase<std::string> : public TypedRealBase<T>
{
// Inherit all the template functionality from TypedRealBase
// string-specific stuff here
}
You don't have to specialize the whole class, only what you want. Works with GCC & MSVC:
#include <string>
#include <iostream>
class Base {};
template <typename T>
class TypedBase : public Base
{
public:
T get();
void set(T t);
};
// Non-specialized member function #1
template <typename T>
T TypedBase<T>::get()
{
return T();
}
// Non-specialized member function #2
template <typename T>
void TypedBase<T>::set(T t)
{
// Do whatever here
}
// Specialized member function
template <>
std::string TypedBase<std::string>::get()
{
return "Hello, world!";
}
int main(int argc, char** argv)
{
TypedBase<std::string> obj1;
TypedBase<double> obj2;
std::cout << obj1.get() << std::endl;
std::cout << obj2.get() << std::endl;
}