Any way to determine if class implements operator() - c++

I'm trying to find is there's a way to check if a class is a functional because i want to write a template which uses it?
Is there an easy way to do this? Or do I just wrap things in a try/catch? Or perhaps the compiler won't even let me do it?

If you have a function template written like:
template <typename T>
void f(T x)
{
x();
}
you will be unable to instantiate it with any type that is not callable as a function taking no arguments (e.g., a class type that overloads operator() taking no arguments is callable as a function that takes no arguments). You would get a compilation error if you tried to do so.
This is the simplest way to require the type with which a template is instantiated to have certain properties: just rely on the type having those properties when you write the template, and if the type doesn't have one of the required properties, it will be impossible to instantiate the template with that type.

There are quite a few ways a parameter type can be applicable to the call syntax
Type is a pointer or reference to a function type, or
Type is a class-type which has a conversion function to one of the types in 1., or has an applicable operator().
The current C++ cannot check for 2., so you are left without checking, like the other answers explain.

This would fall under doing it and getting a compiling error. When the code is compiled the template function or template classes are are expanded for the types used as if there were duplicate copies of that template code, one for each type.
So you can basically do whatever and as long as all the types used for your templates support it you have no problem. If they don't support it you have a compiling error and you can't run your code without fixing it.
template <typename T>
void DoIt(T a)
{
a.helloworld();//This will compile fine
return a();//This will cause a compiling error if T is B
}
class A
{
public:
void a.helloworld(){}
void operator()(){}
};
class B
{
public:
void a.helloworld(){}
};
int main(int argc, char**argv)
{
A a;
B b;
DoIt(a);
DoIt(b);//Compiling error
return 0;
}

If you actually need a test to see if type T implements an operator() of some given signature then you could use the same SFINAE trick used to identify the existence of any other class member that is discussed here: C++ "if then else" template substitution

Related

Using Concepts to create static polymorphic interface

Hello Stackoverflow community,
I've been really confused on the concepts syntax and am having a hard time getting started.
I would like to create a polymorphic interface for two types of operator types: unary and binary and opted to try out the concept feature in c++20.
Not sure if it matters, but I used a CRTP create my unary functor compatible with binary functors, however I would like to get rid of that. Here's what I have so far:
template <typename T>
concept UnaryMatrixOperatable = requires(T _op) {
_op.template operate(std::unique_ptr<Matrix::Representation>{});
{_op.template operate() } -> same_as<std::unique_ptr<Matrix::Representation>>;
};
class ReLU : public UnaryAdapter<ReLU> {
public:
std::unique_ptr<Matrix::Representation> operate(
const std::unique_ptr<Matrix::Representation>& m);
};
static_assert(UnaryMatrixOperatable<ReLU>);
However, I am getting a compilation error, presumably because I am not doing some sort of template specialization for a const matrix & type?
include/m_algorithms.h:122:13: error: static_assert failed
static_assert(UnaryMatrixOperatable<ReLU>);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
include/m_algorithms.h:122:27: note: because 'Matrix::Operations::Unary::ReLU' does not satisfy 'UnaryMatrixOperatable'
static_assert(UnaryMatrixOperatable<ReLU>);
^
include/m_algorithms.h:53:26: note: because '_op.template operate(std::unique_ptr<Matrix::Representation>{})' would be invalid: 'operate' following the 'template' keyword does not refer to a template
_op.template operate(std::unique_ptr<Matrix::Representation>{});
^
Thanks for all the help in advance, this design in my code has been problematic for over a week so I'm determined to find a clean way to fix it! Thanks.
Concepts are not base classes, and you should not treat concept requirements like base class interfaces. Base classes specify exact function signatures that derived classes must implement.
Concepts specify behavior that must be provided. So you explain what that behavior is.
The behavior you seem to want is that you can pass an rvalue of a unique pointer to an operate member function. So... say that.
template <typename T>
concept UnaryMatrixOperatable = requires(T _op, std::unique_ptr<Matrix::Representation> mtx)
{
_op.operate(std::move(mtx));
};
There's no need for template here because you do not care if operate is a template function. It's not important in the slightest to your code if any particular T happens to implement operate as a template function or not. You're going to call it this way, so the user must specify some function interface that can be called a such.
The same goes for the zero-argument version. Though your interface should probably make it much more clear that you're moving from the unique pointer in question:
template <typename T>
concept UnaryMatrixOperatable = requires(T _op, std::unique_ptr<Matrix::Representation> mtx)
{
_op.operate(std::move(mtx));
{ std::move(_op).operate() } -> std::same_as<decltype(mtx)>;
};
In any case, the other reason you'll get a compile error is that your interface requires two functions: one that gets called with an object and one that does not. Your ReLu class only provides one function that pretends to do both.

Combining templates and type safety

Let's say I have several functions defined like this:
template <typename T>
inline void read<bool>(T **data) {
//some code
}
template <typename T>
inline void read<double>(T **data) {
//some other code
}
template <typename T>
inline void read<int>(T **data) {
//also different code
}
Now, I create another function defined like this:
template<typename T>
inline void readMultiple(T **data, int counter) {
for (int i = 0; i < counter, ++i) {
read<T>(data);
}
}
(1)That would call the appropriate read<T>(T **data) implementation based on the type T, right?
(2)If I were to specify a type that is not one of the three above, I'd get a compilation error, since that function is not defined, right?
(3)Also, can I make this call:
double **d;
read<double>(d);
to ensure that I called the implementation for double?
I know I'd get the same result without the <double> part, but this way I'm ensuring that double is passed to the function, where as doing it without <double> would allow for d to be a int or a bool and the code would still compile, silently introducing an error.
(1)That would call the appropriate read<T>(T **data) implementation based on the type T, right?
Yes, assuming the specializations are visible at the point where read<T>(data) is encountered.
(2)If I were to specify a type that is not one of the three above, I'd get a compilation error, since that function is not defined, right?
You haven't provided your declaration of the template read() function, so this can't be answered. Assuming that you have declared it like template <typename T> void read(T**); and have not defined it anywhere then yes, you would get a link-time error when the linker is unable to find an implementation of the requested specialization.
(3)Also, can I make this call:
double **d;
read<double>(d);
to ensure that I called the implementation for double?
You can, though <double> is superfluous and will be inferred.
... silently introducing an error.
If the thing you're passing is a bool** then it would not be an error to use the bool specialization. I don't really see any benefit from explicitly providing the template arguments. If bool** is the wrong type then presumably you would be getting errors somewhere else, anyway.
I guess it depends on what you mean by "silently introducing an error." It's not clear what kind of error you're trying to prevent. I can come up with a contrived example, but contrived examples rarely represent real-world dangers.
Two side notes:
The syntax for your specializations is incorrect. It should be template <> inline void read<bool>(bool **data) { /* ... */ } for example.
There's no need for templates here at all, you can just have three function overloads. Having an undefined template function with explicit specializations is an anti-pattern; overloads are the recommended way to implement the same thing.

C++ Calling function that has template which has inheritance

So I have a class that defines a TileGrid:
template<typename T>
class TileGrid { ... };
I fill in the template with a class called ImageTile
class ImageTile { ... };
I have a child class of ImageTile that I have defined that looks like this:
class FFTWImageTile : public ImageTile { ... };
In a separate file I define the following function:
void writeDataToFile(TileGrid<ImageStitching::ImageTile> * grid, std::string fileName);
(note: both ImageTile and FFTWImageTile are in the ImageStitching namespace)
Now all of the above compiles just fine, but when I try to use it I get an error.
Here is an example test case that is using it:
namespace is = ImageStitching;
TileGrid<is::FFTWImageTile> * grid = new TileGrid<is::FFTWImageTile> ( ... );
writeTranslationsToFile(grid, "output.txt");
When compiling the test case I get the following error:
error: cannot convert ‘TileGrid<ImageStitching::FFTWImageTile>*’ to ‘TileGrid<ImageStitching::ImageTile>*’ for argument ‘1’ to ‘void writeTranslationsToFile(TileGrid<ImageStitching::ImageTile>*, std::string)’
Anyway I can make this happen in C++?? I've looked all over and cant seem to find some help with making a function that has a parameter featuring a template that has child/parent relationships.
Edit:
Everyone's answers have been exceptional and each solve the issue presented. I think decided to move to C++11 and use an assert for this particular case. In the future I think I will add a template to the function and ensure to get the data that way. Thank you all for the help! I have marked what I think is the best answer although each have been acceptable.
You are getting the error because despite that FFTWImageTile is derived from ImageTile, TileGrid<FFTWImageTile> and TileGrid<ImageTile> are absolutely unrelated classes.
How to fix this depends on the implementation of the classes which you haven't shown. Perhaps you can make writeDataToFile() templated:
template<typename T>
void writeDataToFile(TileGrid<T> * grid, std::string fileName);
Options that might work for you.
Make writeDataToFile a function template.
template <typename T>
void writeDataToFile(TileGrid<T> * grid, std::string fileName);
In the implementation of this function, use another function template to write individual elements of the tile.
template <typename T>
void writeTileElement(T const& tileElement, std::ostream& out);
You can create overloaded versions of writeTileElement to take care of special handling of different types of objects.
Use a TileGrid of ImageTile* instead of ImageFile.
void writeDataToFile(TileGrid<ImageStitching::ImageTile*> * grid, std::string fileName);
You generate two different classes with
TileGrid<ImageStitching::ImageTile>
and
TileGrid<is::FFTWImageTile>
They have no relation other than being generated from the same template. You would want to derive from the class TileGrid<ImageStitching::ImageTile> to have an actual subclass for type purposes.
You could templatize the function writeDataToFile, but to enforce type restrictions on template arguments, you should use something like...
static_assert(is_base_of<T, ImageStitching::ImageTile>>(), "T is not a base of ImageTile");
static_assert
is_base_of

C++: force complete template compilation (MSVC/G++)

Hello and good day to you.
Following code fragment compiles on cl.exe (15.00.30729.01) and mingw-g++ (4.4.0):
template<typename T> class Test{
public:
T t;
void error(){
int doesNotExist = 6;
return doesNotExist;//<---- void function returning result
}
};
int main(int argc, char** argv){
Test<int> test;
return 0;
}
Also, on cl.exe you can even get away with something like this:
template<typename T> class Test{
public:
T t;
void error(){
doesNotExist = 6;//<---- undeclared variable
return doesNotExist;//<---- void function returning result
}
};
Now, this obviously happens because compiler does not create contents for methods of a template class until somebody calls them. However, this may pose problems when you're designing large template class (because you're very likely to forget to add test call to new method somewhere).
The question:
Is there a compiler switch for g++ or cl.exe that would force compiler to process entire template (so this code fragment will trigger compilation error)?
If you want to test the template with a couple of types, you can trigger manual instantiations of the types, as in:
// at namespace level
template class Test<int>;
Explicit instantiations of class templates automatically trigger the instantiation of all members, which seems to be what you want.
The actual problem is that the language is designed to explicitly allow the behavior that you want to avoid. When a class template is implicitly instantiated, the compiler will instantiate only those methods that are used. The main use case of the feature is that some methods might impose stricter requirements on the instantiating type than others, if all methods were instantiated always then the class template could only be used with those types that fulfill the stricter requirements.
By allowing the compiler to only instantiate those methods that are used, the class template can be used with types that don't meet all of the requirements of all of the methods, as long as they meet the requirements of the methods that are actually used.
A common example is operator[] in std::map<> that requires the value_type to be default-constructible (operator[] will create a new object default initialized if the key is not present in the container and return a reference to it). The behavior in the language allows you to use std::map on types that are not default-constructible as long as you don't use operator[] (or any other member function that imposes that requirement).

How to implement template class with template-dependent signal member from boost?

I try to implement a template class which requires to have a signal member that depends on the template argument. My first idea was to realize it like the following:
template<class T>
class SignalClass
{
typedef boost::signals2::signal<void (T &)> OnReceive;
public:
SignalClass(const OnReceive::slot_type &_slot)
{
m_onReceive.cnnect(_slot);
}
virtual SignalClass(){};
void Send(T &_val)
{
m_onReceive(_val);
}
private:
OnReceive m_onReceive;
};
An that class should be used like:
class SignaledClass
{
public:
SignaledClass(void)
{
SignalClass<int> var1(boost::bind(&SignaledClass::ReceiveINT, this));
SignalClass<double> var2(boost::bind(&SignaledClass::ReceiveDOUBLE, this));
}
void ReceiveINT(int &_val)
{
...
}
void ReceiveDOUBLE(double &_val)
{
...
}
}
(BTW: I know, that it makes no sense to create the SignalClass object just inside the constructor. It's just to understand my problem.)
It is important for me to realize a delegate-like concept with a template as signal parameter.
The problem is that the constructor code doesn't work.
But I found a solution.
If I additionally specify an additional typedef like
typedef typename OnReceive::slot_type slot_type;
and use that a parameter for the constructor, like
PushInputSlot(const slot_type& _slot);
the it works.
But I have no real clue why.
I hope that somebody can help me.
Thanx,
Frank
P.S.: I'm new on stackoverflow thats why I'm not familiar with the rules here. Hope I've done everything in the right way... ;-)....
Here is the reason why adding typename (either directly in the constructor argument or in an additional typedef) works:
First, the type OnReceive is a so-called "dependent type", because it depend on the type of the template parameter.
Then, templates are processed in two stages in the compiler: The first stage is when the compiler encounters the source text for the template and the second stage is when the template is actually instantiated.
During the first stage of processing, the compiler will (should) try to validate as far as possible that the template definition is correct, but it runs into a problem when it comes to dependent types. Because a dependent type depends on the template parameters, the compiler does not know what the actual type will look like.
In particular, when accessing a member with the :: operator, the compiler needs some help deciding if the member is expected to refer to a member-type (typedef or nested class) or a non-type member (a variable, enum, etc.). This can be resolved by adding typename before the (full) type-name if you know that it should refer to a type.
The other place where the compiler might have a problem is differentiating between a member-template and a non-template member involved in a less-than comparison. This is resolved by adding the keyword template before the name of the member-template (immediately after the operator).