Using C++11, I'd like to call a static member function template without qualifying it with the scope of its enclosing class:
struct Test {
template<typename T>
static bool Function(T x)
{ /* ... */ }
};
int x;
Test::Function(x); // I don't want to write this
Function(x); // I want to be able to write this instead
I can define another function with the same signature at global scope and forward the arguments, but I'd prefer a solution that doesn't force me to write another function. I'd also like to avoid using a macro.
This question is related:
(using alias for static member functions?)
but doesn't seem to cover the case of function templates.
Sure, you can alias the templated function if you want to do a little work with the using keyword first:
template<typename T>
using testfn = bool (*)(T);
and then create a pointer to the function with:
testfn<int> fnPointer = Test::Function;
and finally call it:
std::cout << boolalpha << fnPointer(x) << std::endl;
Live Demo
If you only ever want to bind to the case where T is int, you can do this:
using testfn = bool (*)(int);
//...
testfn fnPointer = Test::Function;
std::cout << boolalpha << fnPointer(x) << std::endl;
Live Demo 2
Edit: If you want a constexpr function pointer like in the accepted answer of the question you linked, that's a pretty simple extension:
constexpr auto yourFunction = &Test::Function<int>;
//...
std::cout << boolalpha << yourFunction(x) << std::endl;
Live Demo 3
I learned this playing with the #andyg answer (probably above mine), but it worked for me and it doesn't require putting a different alias for every template.
It requires c++14 or later though.
Step 1 - magical template alias:
template <typename T> constexpr auto funky1 = &Test::Function<T>;
Step 2 - lambda means you don't need to pass the template argument:
auto funky = [](auto in) { return funky1<decltype(in)>(in); };
full example
Also, inline full example:
#include <iostream>
struct Test {
template <typename T> static bool Function(T x) { return true; }
};
// Magical template alias
template <typename T> constexpr auto funky1 = &Test::Function<T>;
// lambda means it'll infer the template parameters when calling
auto funky = [](auto in) { return funky1<decltype(in)>(in); };
int main() {
int x = 0;
// Just use the `funky1` version, but you have to specify the template parameters
std::cout << "string: " << funky1<std::string>("I'm a string") << std::endl
<< "int: " << funky1<int>(42) << std::endl
<< "bool: " << funky1<bool>(true) << std::endl;
// Use the `funky` version, where template parameters are inferred
std::cout << "string: " << funky("I'm a string") << std::endl
<< "int: " << funky(42) << std::endl
<< "bool: " << funky(true) << std::endl;
return 0;
}
Related
Hi I'm trying to pass a tuple as a parameter to a function.
I would like to not to specify the amount of elements in the tuple (I followed this example: tuple as function argument)
What is missing now is how I can count the number of element into the tuple in order to access it with std::get
#include<tuple>
#include<iostream>
template <typename... T> void fill(std::tuple<T...> values) {
std::cout << std::tuple_size<T...>::value << '\n';
//std::cout << std::get<0>(values) << '\n';
//std::cout << std::get<1>(values) << '\n';
}
int main() {
fill(std::make_tuple(2.));
fill(std::make_tuple(2., 5));
}
tuple_size seems not suitable to be used (https://en.cppreference.com/w/cpp/utility/tuple/tuple_size)
Lets look at the example in the provided reference:
template <class T>
void test(T t)
{
int a[std::tuple_size<T>::value]; // can be used at compile time
std::cout << std::tuple_size<T>::value << '\n'; // or at run time
}
int main()
{
test(std::make_tuple(1, 2, 3.14));
}
From this example (as well as from the reference itself, see e.g. the second declaration), it could be deduced that the template argument to std::tuple_size is the tuple type.
As in (in your case)
std::cout << std::tuple_size<std::tuple<T...>>::value << '\n';
// ^^^^^^^^^^^^^^^^
// Note: The tuple type is used here
I observed that if I explicitly delete only constructor and destructor of a class then the resultant implementation deletes copy constructor & move constructor, but the compiler still makes copy assignment and move assignment operators implicitly available! Which in turn makes assignment possible!
My question is what is the rational of this? What is the use case where this can be used. Following is an example code for reference:
# ifndef MOEGLICH_H_
# define MOEGLICH_H_
# include <cstdint>
class Moeglich final
{
public :
explicit
Moeglich() = delete ;
~Moeglich() = delete ;
/*
// With explicit deletion
Moeglich& operator=(const Moeglich& other) = delete ;
Moeglich(const Moeglich& other) = delete ;
Moeglich&& operator=(Moeglich&& other) = delete ;
Moeglich(Moeglich&& other) = delete ;
*/
static constexpr uint16_t Egal(const uint8_t& var_) noexcept
{
return static_cast< uint16_t > ( var_ ) ;
}
};
# endif
# include <cstdlib>
# include <iostream>
# include <type_traits>
int main(int argc, char* argv[])
{
std::cout << std::boolalpha
<< "Is constructible : " << std::is_constructible<Moeglich>::value << std::endl
<< "Is destructible : " << std::is_destructible<Moeglich>::value << std::endl
<< "Is copy constructible : " << std::is_copy_constructible<Moeglich>::value << std::endl
<< "Is move constructible : " << std::is_move_constructible<Moeglich>::value << std::endl
<< "Is copy assignable : " << std::is_copy_assignable<Moeglich>::value << std::endl
<< "Is move assignable : " << std::is_move_assignable<Moeglich>::value << std::endl
<< "Is assignable : " << std::is_assignable<Moeglich, Moeglich>::value << std::endl
;
/* Following were what I wanted to prevent anyway :
const Moeglich mom {} ;
Moeglich pop {} ;
Moeglich foo {} ;
foo = mom ;
foo = std::move(pop) ;
*/
return EXIT_SUCCESS ;
}
Edit:: I see I have created a lot of confusion by vaguely putting some codes and not mentioning intent. I will never construct this object. All I am interested is accessing
const uint8_t duh { 5 } ;
const uint16_t notEgal { Moeglich::Egal(duh) } ;
Here is what is important for me: Sometimes, I need partial template specialization of functions which is not allowed which can be enabled if I put this function inside a template class.
I have been pointed to a link here, which very clearly lays down the rule. My expectation from the compiler was wrong and my use-case cannot be understood in a special way by the compiler.
Thanks everybody for commenting.
Regards,
Sumit
In the following code, as none of the arguments is const, i can't understand why the second overload is called in the 3 following cases.
#include <iostream>
#include <algorithm>
using namespace std;
void ToLower( std::string& ioValue )
{
std::transform( ioValue.begin(), ioValue.end(), ioValue.begin(), ::tolower );
}
std::string ToLower( const std::string& ioValue )
{
std::string aValue = ioValue;
ToLower(aValue);
return aValue;
}
int main()
{
string test = "test";
cout<<"Hello World" << endl;
// case 1
cout << ToLower("test") << endl;
// case 2
cout << ToLower(static_cast<string>(test)) << endl;
// case 3
cout << ToLower(string(test)) << endl;
}
In all 3 cases you are creating a temporary std::string, this is an unnamed object, an R-value. R-values aren't allowed to bind to non-const l-value references (T&) and so only the overload taking const std::string& ioValue is valid.
The reasoning is the return type is std::string for the second function but void for the first. std::cout << (void) << std::endl is not a valid set of operations. std::cout << (std::string) << std::endl is. If you return a std::string& from the first function you'd probably see #2 & #3 probably use your first function call.
I have the following use of std::reference_wrapper for a build in type (double) and for a user defined type (std::string).
Why do they behave differently in the case of the stream operator?
#include<functional> //reference wrapper
#include<iostream>
void fd(double& d){}
void fs(std::string& s){}
int main(){
double D = 5.;
std::reference_wrapper<double> DR(D);
std::cout << "DR = " << DR << std::endl; //ok
fd(DR); // ok
std::string S = "hello";
std::reference_wrapper<std::string> SR(S);
std::cout << "SR = " << static_cast<std::string&>(SR) << std::endl; // ok
std::cout << "SR = " << SR << std::endl; // error: invalid operands to binary expression ('basic_ostream<char, std::char_traits<char> >' and 'std::reference_wrapper<std::string>')
fs(SR); // ok
}
http://coliru.stacked-crooked.com/a/fc4c614d6b7da690
Why in the first case DR is converted to double and printed and in the second it is not? Is there a work around?
Ok, I see now, in the ostream case I was trying to called a templated function that is not resolved:
#include<functional> //reference wrapper
void double_fun(double const& t){};
template<class C>
void string_fun(std::basic_string<C> const& t){};
int main(){
double D = 5.;
std::reference_wrapper<double> DR(D);
double_fun(DR); //ok
std::string S = "hello";
std::reference_wrapper<std::string> SR(S);
string_fun(SR); // error: no matching function for call to 'string_fun'
string_fun(SR.get()); // ok
string_fun(static_cast<std::string&>(SR)); // ok
string_fun(*&SR); // would be ok if `std::reference_wrapper` was designed/coded differently, see http://stackoverflow.com/a/34144470/225186
}
For the first part TC gave you the answer. That is, operator<< for basic_string is templated, and template argument deduction doesn't look through implicit conversions.
You could alternatively call SR.get() if you don't want to explicitly to static_cast your reference wrapper.
Now for the second part, string_fun takes as input arguments std::basic_string<C> objects. When you call:
string_fun(SR);
with SR as input parameter which is of type std::reference_wrapper<std::string>, naturally you get a type mismatch.
What you can do is provide an additional overload:
template<class C>
void string_fun(std::reference_wrapper<std::basic_string<C>> const& t) {
};
Live Demo
Or if you want a more unified treatment you could define your string_fun to take template template arguments, and resolve the type with some kind of type trait magic like bellow:
template<template<typename...> class C, typename T>
void
string_fun(C<T> const &t) {
std::cout <<
static_cast<std::conditional_t<
std::is_same<
std::reference_wrapper<T>, C<T>>::value, T, std::basic_string<T>>>(t) << std::endl;
}
Live Demo
I have implemented a logging class TLogFile and now I want to overload the output operator<<.
I want to use the log like this:
TLogFile* log = new TLogFile("some arguments...");
*log << "Hello world."; // (1)
*log << "Hello world." << endl; // (2)
*log << std::hex << setw(2) << setfill('0') << someValue << endl; // (3)
I used ostream as a class member and as a friend. The class looks like this:
namespace app {
class TLogFile
{
public:
app::TLogFile& operator<< (std::string& out);
std::ostream& operator<< (std::ostream& out);
friend std::ostream& operator<< (std::ostream& out, TLogFile& o);
};
} // namespace app
Only plain text (1) is working by using the string version. A soon as I use endl (2) or iomanip (3) I get error messages:
../src/main.cpp:164:70: error: no match for 'operator<<' in 'sysdat.app::cSystemData::obj.app::cSystemObjects::applicationLog->app::TLogFile::operator<<((* & std::basic_string(((const char*)"sysdat.obj.applicationLog <<"), ((const std::allocator*)(& std::allocator()))))) << std::endl'
../src/main.cpp:164:70: note: candidates are:
../src/inc/logger.h:85:17: note: app::TLogFile& app::TLogFile::operator<<(const string&)
../src/inc/logger.h:85:17: note: no known conversion for argument 1 from '' to 'const string& {aka const std::basic_string&}'
../src/inc/logger.h:88:17: note: std::ostream& app::TLogFile::operator<<(std::ostream&)
../src/inc/logger.h:88:17: note: no known conversion for argument 1 from '' to 'std::ostream& {aka std::basic_ostream&}'
../src/inc/logger.h:93:23: note: std::ostream& app::operator<<(std::ostream&, app::TLogFile&)
../src/inc/logger.h:93:23: note: no known conversion for argument 1 from 'app::TLogFile' to 'std::ostream& {aka std::basic_ostream&}'
I believed that one of the ostream version should work.
Has anyone an idea how to overload the operator so that endl and iomanip can be used?
Your operator<< is able to take only std::ostream& and std::string&
(note: probably it should be const std::string&).
The most elegant solution I can imagine is to write a template:
class TLogFile{
protected:
std::ostream* stream;
public:
/* default ctor, copy ctor and assignment operator: */
TLogFile(std::ostream& _stream=std::clog):stream(&_stream){}
TLogFile (const TLogFile&) =default;
TLogFile& operator= (const TLogFile&) =default;
/* std::endl is overloaded,
* so I think compiler doesn't know which version to use.
* This funchtion handles function pointers, including std::endl
*/
inline TLogFile& operator<< (std::ostream&(*func)(std::ostream&)){
(*stream) << func;
return *this;
}
/* should handle everything else */
template<typename T>
inline TLogFile& operator<< (const T& t) {
(*stream) << t;
return *this;
}
}
See it working in online compiler
This way your objects' operator<<s should be able to take anything that std::ostream's can take.
Edit:
Next time, please say that you want to have custom std::endl.
I'm not sure that function with signature
inline TLogFile& operator<< (std::ostream&(*func)(std::ostream&))
is used only when std::endl is passed to it. My previous solution seems inelegent or even inworking. I'm wondering about how to change behaviour of std::endl when it's passed to object of different class.
Notes:
In most cases I'd like to use '\n instead of std::endl.
TLogFile* log = new TLogFile("some arguments...");
I think using raw pointer isn't the best idea here (it's easy to forget about delete),
unless you have to explicitly decide when the object should die.
When the object should die when the current scope does, it should be a local variable:
TLogFile log("some arguments...");
//Usage:
log << "Hello world."; // (1)
log << "Hello world." << endl; // (2)
log << std::hex << setw(2) << setfill('0') << someValue << endl; // (3)
If the object is used in multiple places, and each of the places uses it independently from others, IMO the best solution is to use std::shared_ptr:
#include <memory>
#include <utility>
auto log=std::make_shared<TLogFile>("some arguments...");
//Usage:
*log << "Hello world."; // (1)
*log << "Hello world." << endl; // (2)
*log << std::hex << setw(2) << setfill('0') << someValue << endl; // (3)
This way the object dies when the last shared_ptr does.
I used pointer in the class to be able to re-assign it. If you don't need re-assignment, you can use reference instead.
Thanks to GingerPlusPlus. I found out, that the operator operator<< (std::ostream&(*func)(std::ostream&)) is called only once for the endl (maybe this assumtion is not always true, Please read remarks/edit above of GingerPlusPlus). I replaced the ostream against a stringstream and write the contens of the stringstream when the operator ist called.
class TLogFile{
protected:
std::ostream* stream;
std::stringstream line;
public:
/* default ctor, copy ctor and assignment operator: */
TLogFile(std::ostream& _stream=std::clog):stream(&_stream){}
TLogFile (const TLogFile&) =default;
TLogFile& operator= (const TLogFile&) =default;
void write() {
// Doing some write stuff
// ...
// Empty stringstream buffer
line.str(std::string());
}
/* std::endl is overloaded,
* so I think compiler doesn't know which version to use.
* This funchtion handles function pointers, including std::endl
*/
inline TLogFile& operator<< (std::ostream&(*func)(std::ostream&)){
line << func;
write();
return *this;
}
/* should handle everything else */
template<typename T>
inline TLogFile& operator<< (const T& t) {
line << t;
return *this;
}
}