How do I pass this instance as a parameter into a function?
class
{
public:
void foo();
} bar;
Do I have to name the class?
It is copyable since I haven't made the class's copy ctor private.
So how is it possible if at all?
Maybe it would be better if you explicit what you want to do. Why do you want to create an unnamed class? Does it conform to an interface? Unnamed classes are quite limited, they cannot be used as parameters to functions, they cannot be used as template type-parameters...
Now if you are implmenting an interface then you can pass references to that interface:
class interface {
public:
virtual void f() const = 0;
};
void function( interface const& o )
{
o.f();
}
int main()
{
class : public interface {
public:
virtual void f() const {
std::cout << "bar" << std::endl;
}
} bar;
function( bar ); // will printout "bar"
}
NOTE: For all those answers that consider template arguments as an option, unnamed classes cannot be passed as template type arguments.
C++ Standard. 14.3.1, paragraph 2:
2 A local type, a type with no
linkage, an unnamed type or a type
compounded from any of these types
shall not be used as a
template-argument for a template
type-parameter.
If you test with comeau compiler (the link is for the online tryout) you will get the following error:
error: a template argument may not
reference an unnamed type
As a side note, comeau compiler is the most standard compliant compiler I know of, besides being the one with the most helpful error diagnostics I have tried.
NOTE: Comeau and gcc (g++ 4.0) give an error with the code above. Intel compiler (and from other peoples comments MSVS 2008) accept using unnamed classes as template parameters, against the standard.
Why should you create an anonymous class when you want to pass it to a function?
Just explicitly declare the class:
class Foo {
// ...
};
void Method(Foo instance);
int main() {
Foo bar;
Method(bar);
}
The 2nd possibility would be using a template-function, so the compiler would infer the type (Note that this is not standard-compatible!)
#include <iostream>
using namespace std;
template <typename T>
void SayFoo(T& arg) {
arg.Foo();
}
int main() {
class {
public:
void Foo() { cout << "Hi" << endl; }
} Bar;
Bar.Foo();
SayFoo(Bar);
return 0;
}
There is no problem with copying the class since the compiler generated the copy constructor automatically and you can use tools like boost::typeof in order to avoid referring to the type explicitly.
BOOST::AUTO(copy, Bar);
Another approch is using (relatively slow) runtime-polymorphism (interfaces/inheritance).
Yes you have to name the class to pass it a instance of to the function. As you have not provided your own copy ctor compiler will generate its own and use it.
Hmmm, nameless class.
You could pass a pointer to it as void *.
Since you cannot refer to it by name, you cannot call its constructor, copy constructor, or destructor except for the one instance, so you cannot copy it.
EDIT: you could still pass it to a template function which could copy it.
REEDIT: edit was wrong.
Related
I would like to store return value of class member function in another class.
This seems to work:
class Foo
{
public:
Foo(int) {} //non default constructor that hides default constructor
unspecified_return_type get_value();
};
class Bar
{
// stores a value returned by Foo::get_value
decltype(Foo().get_value()) value;
};
However there is a reference to default constructor of class Foo, which may not be defined in some cases. Is there any way to do it without explicitly referring to any constructor?
Yup, there is. std::declval was introduced for exactly this reason (not needing to rely on a particular constructor):
decltype(std::declval<Foo>().get_value()) value;
You could do it with the help of std::declval like the example below:
#include <iostream>
#include <utility>
struct test {
int val = 10;
};
class Foo {
public:
test get_value() { return test(); }
};
class Bar {
public:
using type = decltype(std::declval<Foo>().get_value());
};
int main() {
Bar::type v;
std::cout << v.val << std::endl;
}
LIVE DEMO
std::declval<T> converts any type T to a reference type, making it possible to use member functions in decltype expressions without the need to go through constructors.
std::declval is commonly used in templates where acceptable template parameters may have no constructor in common, but have the same member function whose return type is needed.
I'm not sure why the following code block compiles and works even though the semantics implied by the template syntax are different. Class A accepts a template type Data and contains a member data of template type Data. It also has a constructor that accepts an instance of Data by value and instantiates the member data with the assumed copy constructor. Another class C has an arbitrary constructor that takes a pointer to some arbitrary class B and stores it as member foo. When Data in A is templated as type C and an A<C> instantiated with arguments that the constructor for C accept (namely, a pointer to a B) one would expect a compiler error because A has not been told how to handle arbitrary arguments and pass them to the Data constructor. It has only been told to use the copy constructor of Data with an existing instance. However, this code compiles with clang and c++11 and prints true. I'm assuming this is a compiler bug, not a feature, but perhaps I'm missing something about how C++ templates work? I'm also curious about the correct syntax for this functionality is, (to pass arbitrary template parameters to the constructor for A and forward them to the constructor for type Data) as that is my actual intent.
#include <iostream>
template<typename Data>
struct A {
Data data;
A(Data data_) : data(data_) { }
};
struct B {
B() { }
};
struct C {
B* foo;
C(B* foo_) : foo(foo_) { }
};
int main() {
B foo;
A<C> thing = A<C>(&foo);
std::cout << (thing.data.foo == &foo) << std::endl;
return 0;
}
EDIT:
correct way is parameter packing
template<typename Data>
struct A {
Data data;
template<class ... Args>
A(Args... args) : data(std::forward<Args>(args)...) { }
};
struct B {
B() { }
};
struct C {
B* foo;
C(B* foo_) : foo(foo_) { }
};
int main() {
B foo;
A<C> thing = A<C>(&foo);
std::cout << (thing.data.foo == &foo) << std::endl;
return 0;
}
The reason your code compiles is because your constructor for struct C is not flagged as explicit. In effect, A<C> object expects a C object in its constructor. But you provide a pointer to b instead. Since none of your single parameter ctors are flagged as explicit, it is legal for the compiler to choose an appropriate conversion from input parameter to the desired parameter.
Usually static code analyzers will flag this as undesirable as you don't ever want automatic or unexpected conversions of this sort. So you really should flag all single parameter ctors with the explicit keyword.
https://en.cppreference.com/w/cpp/language/explicit
I have a class template whose constructor accepts a callable whose type is a template parameter. I would like to have that type deduced so I don't have to specify it whenever instantiating the class.
Unfortunately, the type deduction doesn't work in the example below. Is there a way to get it to work?
template<typename F>
class C {
public:
C(F&& f) : m_f{f} {}
private:
F m_f;
};
class D {
public:
static int s() { return 0; }
private:
C<decltype(&s)> c {&s}; // OK
C<> c2 {&s}; // error, not enough template parameters
};
https://wandbox.org/permlink/8cphYR7lCvBA8ro4
Note this is similar to Can template parameter deduction be used in class data members? but here I'm asking about getting something similar to work, not about standard compliance.
One more note is that while re-specifiying the type of the template parameter in the example above is just a non-DRY inconvenience (which one of the answers below suggests solving with a macro), I'm not sure how it would be possible to have an instance of C with F being a non-global lambda function type (e.g. one that's defined on the spot), in case that instance is a data member. A technique which would allow that would be very powerful and useful, IMHO.
If your main goal is to avoid typing &s twice, the pragmatic solution is to define a macro:
#define CC(name,value) decltype(C{value}) name{value}
class D {
public:
static int s() { return 0; }
private:
CC(c,&s);
// lambda still not possible:
// CC(c2,[](){return 42;});
};
You could do something like this:
decltype(C{&s}) c{&s};
But I'm not aware of a way to avoid duplicating the &s.
C++ templates allow we put whatever in our objects with template arguments. However, if our template arguments use functions/variables which belong to certain types, how do we check?
template<typename BarType>rguments
class Foo {
public:
Foo() { bar = new BarType() }
private:
BarType * bar;
}
Foo<Bar> …
BarType could be anything derived from a Bar superclass.
What happens if we invoke some functions which only belong to Bar in our Foo class? What happens if we pass non-BarType? Do we have anyway to check?
You will get a compile-time error if your templated code makes reference to members that the actual parameter doesn't provide when you try to instantiate the template. So don't worry, you won't be able to break anything.
Think of templates as a code-generation mechanism. Whether the generated code actually makes sense can sometimes only be determined when you actually try it.
Given the class template TempFoo below, you see that it calls the example function of the templated T type in its constructor. The first two types work because they both define example; the third doesn't.
template<typename T>
class TempFoo
{
void TempFoo() {
T obj;
obj.example();
}
};
class First {
void example() {}
};
class Second {
void example() {}
};
class Third {
};
int main()
{
TempFoo<First> f; // works
TempFoo<Second> s; // works
TempFoo<Third> t; // doesn't
}
Whatever you're giving in the tempalte parameter list is simple a place place holder. Compiler will repalce with appropriate types according to the type of object which is used to instantiate the template class. A compile-time error will be appear if the object doesn't satify the operations done in the functions. Also it's a good practice to use 'T' as place holder.
An easy way to ensure that the template parameter derives from the base class:
template<typename BarType>
class Foo
{
// ...
~Foo() { Bar* p = (BarType*)0; }
};
The compiler will type-check the assignment, generating an error if Bar isn't an unambiguous supertype of BarType, and then optimize away the unused local variable.
What's the rationale behind the hiding rule in C++?
class A { void f(int); }
class B : public A { void f(double); } // B::f(int) is hidden
If it is a meaningful feature I think it should also be possible to hide functions without defining new functions with the same name: something like this:
class B : public A { hide void f(double); }
but this is not possible.
I don't think it simplifies compilers job, since compilers must anyway be able to unhide functions when you explicitly use the using directive:
class B : public A { using A::f; void f(double); } // B::f(int) NOT hidden
So, how come there is a hiding rule?
It's an hairy question, but apparently the idea is that this hiding feature helps avoiding subtle bugs when making changes to a base class (that could otherwise "steal" calls that before would have been handled by the derived class). Still a change in a base class can influence the result of compilation of derived classes so I don't think I understand 100% this explanation.
I agree that this topic is so frequently discussed that probably the hiding actually increases the amount of "surprises" in C++ programmers.
A detailed discussion about this issue can be found here...
i don't know the original rationale, but since hide or not hide are about equally bad choices wrt. to functions, i'm guessing the rationale is to have uniform rules: the same as for names defined in nested curly-braces scopes.
the hiding helps you in some ways.
adding a method to a base class will by default not affect overload resolution for a derived class.
and you do not run afoul of overload resolution by some mishap directing your call with say argument false, to a base class method with formal argument void*. such things.
cheers & hth.,
I'm sure I've seen this case offered by a C++ bigwig, not sure which:
struct Base {
void f(const Base&);
};
struct Derived : Base {
using Base::f;
void f(double);
};
int main() {
Derived d;
d.f('a'); // calls Derived::f
}
Now, add void f(int); to Base, and the meaning of main changes - it calls Base::f because int is a better match for char - it's an integer promotion rather than a standard conversion.
It's not clear whether that change to the base would really be intended by the programmer to catch calls with char, so requiring using to be explicit means the default behavior is that the change doesn't affect the calling code. I believe it's a marginal call, but I think the committee decided that base classes in C++ were fragile enough as they are, without this too :-)
There's no need for a "hide" keyword because there's no comparable case for hiding "f" from the Base when it isn't overloaded in Derived.
Btw, I've chosen the types, and char is deliberately incongruous. You can get more subtle cases with int vs unsigned int rather than int vs char.
Another reason for hiding base class's member function (with same name but different signatures) might be due to ambiguity caused by optional parameters. Consider the following example:
#include <stdio.h>
class A
{
public:
int foo(int a, int b=0)
{
printf("in A : %d, %d\n", a, b);
}
};
class B : public A
{
public:
int foo(int a)
{
printf("in B : %d\n", a);
foo(a); //B:foo(a) will be called unless we explicitly call A:foo(a)
foo(a, 1); // compile error: no matching function for call to B:foo(int&, int)
}
};
int main()
{
B b;
b.foo(10);
return 0;
}
If the foo method in base class hadn't become hidden, it wouldn't be possible for compiler to decide whether A::foo should be called or B::foo since the following line matches both signatures:
foo(a);
Probably, the reason is template specialization. I give you an example:
template <int D> struct A { void f() };
template <> struct A<1> { void f(int) };
template <int D>
struct B: A<D>
{
void g() { this->f(); }
};
The template class B has a method f(), but until you don't create an instance of the class B you don't know the signature. So the call this->f() is anytime "legal". Both GCC and CLang don't report error until you create the instance. But when you call the method g() on a B<1> instance they indicate the error. So the hiding rule keep simpler to check if your code is valid.
I report the last part of code used in my example.
int main (int argc, char const *argv[])
{
B<0> b0; /* valid */
B<1> b1; /* valid */
b0.g(); /* valid */
b1.g(); /* error: no matching function for call to ‘B<1>::f()’ */
return 0;
}