In Checking a member exists, possibly in a base class, C++11 version, we developed a C++11 version of the classical member-checking type-trait from SFINAE to check for inherited member functions that also works with C++11 final classes, but uses C++11 features (namely, decltype), too:
template<typename T>
class has_resize_method {
struct Yes { char unused[1]; };
struct No { char unused[2]; };
static_assert(sizeof(Yes) != sizeof(No));
template<class C>
static decltype(std::declval<C>().resize(10), Yes()) test(int);
template<class C>
static No test(...);
public:
static const bool value = (sizeof(test<T>(0)) == sizeof(Yes));
};
MSVC has had final as a non-standard extension named sealed since VS2005, but decltype has only been added in VS2010. That leaves VS2005 and 2008 where a class that is marked as sealed still breaks the classical type-trait and the C++11 version cannot be used.
So, is there a way to formulate has_resize_method such that it works on VC2005/08 sealed classes, too?
Obviously, just as using C++11-only features to work around a C++11-only problem (final) is fine, so would be using VS-only extensions to work around the VS2005/08-only problem of sealed classes, but if there's a solution that works for all three sets of compilers {C++11,{VS2005,VS2008},all others}, that would be cool, but probably too much to ask for :)
I was able to come up with a solution that works in all major compilers. Sadly, there is a preprocessor check for MSVC because it complains about the solution for other compilers. The main difference is that MSVC does not accept function pointers inside sizeof() and conversely, GCC does not seem to accept (&C::resize == 0) in the check. Clang happily accepts both.
#include <iostream>
class Base {
public:
void resize(int, int, int) { }
};
class Derived : public Base {
};
class Unrelated { };
template<typename T>
class has_resize_method {
struct Yes { char unused[1]; };
struct No { char unused[2]; };
#ifdef _MSC_VER
template <class C>
static Yes test(char (*)[(&C::resize == 0) + 1]);
#else
template <class C>
static Yes test(char (*)[sizeof(&C::resize) + 1]);
#endif
template<class C>
static No test(...);
public:
static const bool value = (sizeof(test<T>(0)) == sizeof(Yes));
};
int main() {
std::cout << (has_resize_method<Base>::value ? "Base has method resize" : "Base has NO method resize") << std::endl;
std::cout << (has_resize_method<Derived>::value ? "Derived has method resize" : "Derived has NO method resize") << std::endl;
std::cout << (has_resize_method<Unrelated>::value ? "Unrelated has method resize" : "Unrelated has NO method resize") << std::endl;
return 0;
}
Output:
Base has method resize
Derived has method resize
Unrelated has NO method resize
Tested on GCC 4.5.3, GCC 4.3.4, Clang 3.0, Visual C++ 2008 and Visual C++ 2010. I don't have access to Visual C++ 2005 but I think it will work there, too. It also compiles on Comeau Online but I cannot guarantee it produces a correct output there.
Works with both final and __sealed classes.
Note though that it checks not only for member functions but for member pointers in general. You might want to add additional checks such as boost::is_member_function_pointer if this behavior is unwanted. Similarly, you might want to add checks for number of arguments/argument types/result types - again, boost will be very helpful here, esp. boost type decomposition.
MSVC has a special statement __if_exists since vs2005. MSDN Link here. You can use it to check the member function name directly. And then check the signature. Following is a simple foo detection example:
template <typename T, typename U>
int8_t FooCheck( void(T::*)(U) )
{
return 0;
}
template <typename T>
int16_t FooCheck( void(T::*)(double))
{
return 0;
}
template <typename T>
int32_t FooCheck(void(T::*)(int))
{
return 0;
}
template <typename T>
class Detector
{
public:
__if_exists(T::foo)
{
enum
{
value = sizeof(FooCheck(&T::foo))
};
}
__if_not_exists(T::foo)
{
enum
{
value = 0
};
}
};
std::cout << Detector<Class>::value << std::endl;
Related
I want to use preprocessor command to control code executive path. Because in this way can save runtime time.
#if (sizeof(T)==1 doesn't comple with error: C1017
template<typename T>
class String
{
public:
static void showSize()
{
#if (sizeof(T)==1)
cout << "char\n";
#else
cout << "wchar_t\n";
#endif
}
};
inline void test()
{
String<char>::showSize();
String<wchar_t>::showSize();
}
The preprocessor runs before the C++ compiler. It knows nothing of C++ types; only preprocessor tokens.
While I would expect any decent compiler to optimize away an if (sizeof(T) == 1), you can be explicit about it in C++17 with the new if constexpr:
template<typename T>
class String
{
public:
static void showSize()
{
if constexpr (sizeof(T) == 1) {
std::cout << "char\n";
} else {
std::cout << "wchar_t\n";
}
}
};
Live Demo
Pre C++17 it's a bit less straightforward. You could use some partial-specialization shenanigans. It's not particularly pretty, and I don't think it will even be more efficient in this case, but the same pattern could be applied in other situations:
template <typename T, size_t = sizeof(T)>
struct size_shower
{
static void showSize()
{
std::cout << "wchar_t\n";
}
};
template <typename T>
struct size_shower<T, 1>
{
static void showSize()
{
std::cout << "char\n";
}
};
template<typename T>
class String
{
public:
static void showSize()
{
size_shower<T>::showSize();
}
};
Live Demo
In this case you could directly specialize String, but I'm assuming in your real situation it has other members that you don't want to have to repeat.
The C and C++ preprocessor is mostly a glorified (well, not that glorious) text replacement engine. It doesn't really understand C or C++ code. It doesn't know sizeof, and it doesn't know C or C++ types. (It certainly won't know what T from your template class is.)
If you want to do things conditionally on T and on sizeof, then you'll need to write C++ code to do it (i.e., if (...) instead of #if ....)
As #some-programmer-dude mentioned in the comment, sizeof is not part of the preprocessor.
you should use if constexpr if you want it to work in compile time.
if you don't care if it happens in compile time or run-time just use a regular if statment
keep in mind that if constexpr is a new feature in C++17!
btw Borland C++ and Watcom C++ support sizeof() in preprocessor expressions, I do not know whether gcc support it.
The locale Facet constructor:
Constructs a copy of other except for the facet of type Facet (typically deduced from the type of the argument) which is installed from the argument facet. If facet is NULL, the constructed locale is a full copy of other. The locale constructed in this manner has no name.
I try to construct using my Facet here, but when I put a break-point in my do_decimal_point and do_thousands_sep they are never called :(
I can see the Facet being passed in, but it's passed into standard library implementation files so I can't see if anything is ever done with it.
I've tried this on Visual Studio 2013, Clang 3.6.0, and gcc 4.9.2. All of them behave as though I had never passed in a Facet just using the other locale's behavior.
I can't find any bugs against this constructor in any of the compilers. I think I'm doing this all the right way. Why can't I get locale to construct using my Facet?
EDIT:
At the request of 0x499602D2 I have added an example. It's interesting to note that the Facet does seem to be picked up but not used with get_money. I'm linking a live example of this (which necessarily useslocale("C") instead of locale("en-US")):
class Foo : public std::moneypunct<char> {
protected:
char_type do_decimal_point() const {
cout << "Hit Foo::do_decimal_point";
return ',';
}
char_type do_thousands_sep() const {
cout << "Hit Foo::do_thousands_sep";
return '.';
}
};
int main()
{
cout.imbue(locale(locale("en-US"), new Foo));
const moneypunct<char>* temp = &use_facet<std::moneypunct<char>>(cout.getloc());
cout << temp->decimal_point() << endl << temp->thousands_sep() << endl;
istringstream USCurrency("1,234.56 -1,234.56 1.234,56 -1.234,56");
USCurrency.imbue(cout.getloc());
long double value;
USCurrency >> get_money(value, true);
return 0;
}
This outputs:
Hit Foo::do_thousands_sepHit Foo::do_decimal_point,
.
I would expect it to output:
Hit Foo::do_thousands_sepHit Foo::do_decimal_point,
.
Hit Foo::do_thousands_sepHit Foo::do_decimal_point
EDIT2:
It appears that moneypunct<char> can't be inherited from as it doesn't get constructed properly, unless it is constructed internally by the locale. Which at least on Visual Studio is a problem because it determines whether to use thousands_sep by the grouping. The work around may be to completely reimplement moneypunct<char>'s functionality. I'm tinkering with that now. In the meantime I've also added a bug here: https://connect.microsoft.com/VisualStudio/feedback/details/1524749/inheriting-from-moneypunct-requires-use-of-unavailable-construction-information
The fact is, do_decimal_place and do_thousands_place are respected by get_money. The difficulty is in the fact that the moneypunct that is being inherited from is being default constructed, so the supporting information to direct get_money to call do_decimal_place and do_thousands_place is not being set up.
Visual Studio's implementation of moneypunct provides two public constructors:
moneypunct()
moneypunct(const _Locinfo& _Lobj, size_t _Refs = 0, bool _Isdef = false)
locale's constructor calls the 2nd moneypunct constructor. Creating a proper _Locinfo is the crux of the problem as that information seems to be implementation specific. The linked Visual Studio Bug requests a way to construct a functional moneypunct without access to implementation details. In lieu of this information all moneypunct fields must be cooked up.
Since this question is about extending an expected working moneypunct the easiest way to do that would be to use an assignment operator or copy constructor. Bad news: both of those are deleted. So punct_facet(const money_punct&) will need to be written internally implementing the behavior of a copy constructor. The values that need to be copied correspond to all the virtual functions that need to be overridden and by punct_facet. In the end your class will end up looking similar to this:
template <typename T>
class punct_facet : public T {
protected:
typename T::string_type m_grouping;
typename T::string_type m_curr_symbol;
typename T::string_type m_positive_sign;
typename T::string_type m_negative_sign;
int m_frac_digits;
typename T::pattern m_pos_format;
typename T::pattern m_neg_format;
typename T::char_type do_decimal_point() const {
return typename T::char_type(',');
}
typename T::char_type do_thousands_sep() const {
return typename T::char_type('.');
}
typename T::string_type do_grouping() const {
return m_grouping;
}
typename T::string_type do_curr_symbol() const {
return m_curr_symbol;
}
typename T::string_type do_positive_sign() const {
return m_positive_sign;
}
typename T::string_type do_negative_sign() const {
return m_negative_sign;
}
int do_frac_digits() const {
return m_frac_digits;
}
typename T::pattern do_pos_format() const {
return m_pos_format;
}
typename T::pattern do_neg_format() const {
return m_neg_format;
}
public:
punct_facet(const T& defaultFacet) : m_grouping(defaultFacet.grouping()),
m_curr_symbol(defaultFacet.curr_symbol()),
m_positive_sign(defaultFacet.positive_sign()),
m_negative_sign(defaultFacet.negative_sign()),
m_frac_digits(defaultFacet.frac_digits()),
m_pos_format(defaultFacet.pos_format()),
m_neg_format(defaultFacet.neg_format()) {}
};
EDIT:
This solution is cross platform but it is also unsatisfactory, because all the members that had to be added to punct_facet already exist in moneypunct. I am not aware of a clean workaround for this fattening. A compiler specific hack is available here: https://stackoverflow.com/a/31454039/2642059
This would result in a punct_facet that looked more like this given that Visual Studio places the v-table pointer as the first item in the object layout:
template <typename T>
class punct_facet : public T {
private:
void Init(const T* money){
const auto vTablePtrSize = sizeof(void*);
memcpy(reinterpret_cast<char*>(this) + vTablePtrSize, reinterpret_cast<const char*>(money) + vTablePtrSize, sizeof(T) - vTablePtrSize);
}
protected:
typename T::char_type do_decimal_point() const {
return typename T::char_type(',');
}
typename T::char_type do_thousands_sep() const {
return typename T::char_type('.');
}
public:
punct_facet(){
Init(&use_facet<T>(cout.getloc()));
}
punct_facet(const T* money){
Init(money);
}
};
Incidentally this implementation of punct_facet is not supported in Clang 3.6.0 but is supported in gcc 5.1.0: http://coliru.stacked-crooked.com/a/e4a1d88b560d6d1b
I found template interfaces very elegant, and trying implementing it faced problem that I can't solve. I hope you can shed some light on it for me.
I have class, for example, forge.h:
template<typename T> class Smelter;
template <typename T>
class Forge
{
long SmeltIt(vector<T>& ore)
{
long res;
Smelter<T> smelter;
for (const auto t : ore)
{
res += smelter.smelt(t);
}
return res;
}
};
With template class Smelter without any realization and template class Forge with realization.
Now, when I want to add class Iron, I need to create iron.h and implement Smelter to use it, this way iron.h:
#include "forge.h"
class Iron {};
template<>
class Smelter<Iron>
{
long smelt(const Iron& iron) { return 5; }
};
int main()
{
vector<Iron> ore;
Iron iron;
ore.push_back(iron);
ore.push_back(iron);
ore.push_back(iron);
Forge<Iron> forge;
cout << forge.SmeltIt(ore); //have to be 15
}
If all this stuff is in one header file, everything perfectly works. But if I create iron.h where I try to implement Smelter, compiler can't find template class Smelter. If I create copy of declaration for Smelter in both forge.h and iron.h, then they conflict with each other.
What is the best solution for that? It would be very useful if I would be able to realize my template interface in other files. Without this such template interfaces becomes ugly, for example, if forge.h is tools, wirely used between projects, and iron.h is my current specialization.
RESULT:
Everything works as expected, problem was outside of described question, in namespaces. All templates, even if it is possible to separate them between different files (that was question) - perfectly works. But they have to share same namespaces.
after fixing some minor issues, your code compiles fine (using clang 3.3) and produces the required result. here is the fixed code (in one file, but in the order of #include)
template<typename T> class Smelter;
template <typename T>
class Forge
{
public:
long SmeltIt(std::vector<T>& ore) // must be public; use std::
{
long res{}; // must be initialized (to 0)
Smelter<T> smelter;
for (const auto t : ore)
res += smelter.smelt(t);
return res;
}
};
class Iron {};
template<>
class Smelter<Iron>
{
public:
long smelt(const Iron& iron) // must be public
{ return 5; }
};
int main()
{
std::vector<Iron> ore; // std::
Iron iron;
ore.push_back(iron);
ore.push_back(iron);
ore.push_back(iron);
Forge<Iron> forge;
std::cout << forge.SmeltIt(ore) // have to be 15
<< std::endl;
}
This is more of a question of how the C++ compiler handles const typeid calls.
Hello! I am trying to make a tuple-style class, configured in such a way that I don't have to rewrite a bunch of the code with specializations.
So this is the general idea:
struct null_type{};
template <typename T1,typename T2=null_type,typename T3=null_type>
class ptestclass
{
private:
template<typename K1,typename K2,typename K3>
class barclass
{
public:
static inline void bar(std::tuple<K1,K2,K3>& vals,K1* otherval1,K2* otherval2,K3* otherval3)
{
Foo(tr1::get<0>(vals),*otherval1);
Foo(tr1::get<1>(vals),*otherval2);
Foo(tr1::get<2>(vals),*otherval3);
}
};
template<typename K1,typename K2>
class barclass<K1,K2,null_type>
{
public:
static inline void bar(std::tuple<K1,K2,null_type>& vals,K1* otherval1,K2* otherval2,null_type* otherval3)
{
Foo(tr1::get<0>(vals),*otherval1);
Foo(tr1::get<1>(vals),*otherval2);
}
};
template<typename K1>
class barclass<K1,null_type,null_type>
{
public:
static inline void bar(std::tuple<K1,null_type,null_type>& vals,K1* otherval1,null_type* otherval2,null_type* otherval3)
{
Foo(tr1::get<0>(vals),*otherval1);
}
};
/*
*Old Bar function...much more readable than bar class, but you cannot partially specialize
*member functions of a class
*
void inline bar(std::tuple<T1,T2,T3> otherval)
{
if (typeid(T1) != typeid(null_type))//constant check hopfully optomized out
{
Foo(vals.get(1),otherval.get(1));
}
if (typeid(T2) != typeid(null_type))//constant check hopfully optomized out
{
Foo(vals.get(2),otherval.get(2));
}
if(typeid(T3) != typeid(null_type))//constant check hopfully optomized out
{
Foo(vals.get(3),otherval.get(3));
}
}
*/
std::tuple<T1,T2,T3> vals;
template<typename K>
void static inline Foo(K& val,K& otherval)
{
//inlineable, short function that is called many (millions) of times per iteration
val += otherval;
}
template<>
void inline Foo<null_type>(null_type& val,null_type& otherval)
{
//inlineable, short function that is called many (millions) of times per iteration
throw "Foo called on null type";
}
public:
ptestclass()
{
printf("made object");
}
void one_iteration(T1* otherval1,T2* otherval2,T3* otherval3,size_t count)
{
for (int i = 0; i < count; ++i)
{
barclass<T1,T2,T3>::bar(vals,otherval1+i,otherval2+i,otherval3+i);
}
}
};
//exposed public class with specialized one_iteration interfaces
template <typename T1,typename T2=null_type,typename T3=null_type>
class testclass : public ptestclass<T1,T2,T3>
{
public:
void one_iteration(T1* otherval1,T1* otherval2,T1* otherval3,size_t count)
{
ptestclass::one_iteration(otherval1,otherval2,otherval3,count);
}
};
template <typename T1>
class testclass<T1,null_type,null_type> : public ptestclass<T1,null_type,null_type>
{
public:
void one_iteration(T1* otherval1,size_t count)
{
ptestclass::one_iteration(otherval1,NULL,NULL,count);
}
};
So my question is is this optimization even possible within C++? If not, it will probably make more sense for me to use an inheritance model on the child nodes rather then a template at this level. However, I am trying to avoid the continual check of the number of types specified and the cost of indirection.
I'm going to start diving into the assembly to see if that is what the compiler does...Just in case this is not standardized behavior, I'm using the Microsoft Visual C++ Compiler 10.0.
I think I misunderstood your question when I put my earlier comment.
Assuming you can use c++11, or you can use boost, you could use something like !std::is_same< T1, null_type >::value /*or boost::is_same...*/ instead of typeid(T1) != typeid(null_type). This uses TMP to resolve to a compile-time constant, which most compilers would have no trouble optimizing away.
This is more of a question of how the C++ compiler handles const typeid calls.
I didn't answer this specific question, but if I understand what you were actually looking for, the above should suffice.
What do i have to do to this code to make it compile, it's braking around this line:
auto val = what.getObject();
#include<iostream>
using namespace std;
class CUP{
public:
void whatsHappening(){}
};
class MUG{
public:
void whatsHappening(){}
};
class CupThrower{
public:
CUP cp;
CUP getObject(){ return cp;}
};
class MugThrower{
public:
MUG mg;
MUG getObject(){return mg;}
};
template <typename T> void whatsHappening(T what){
auto val = what.getObject(); //DOES NOT COMPILE
val.whatsHappening();
}
int main(){
CupThrower ct;
MugThrower mt;
whatsHappening(ct);
whatsHappening(mt);
return 0;
}
i am using VS2008 to compile.
Auto isn't supported in VS2008. Use VS2010 and later versions, or another compiler supporting this feature.
Others have said that auto isn't in VC9, which is sort-of true. auto doesn't mean in the current C++ Standard what it means in C++0x. In the current Standard, it effectively means nothing useful. Long story short, you can't use auto the way you're trying to use it here.
But there is an alternative. In this code:
template <typename T> void whatsHappening(T what){
auto val = what.getObject(); //DOES NOT COMPILE
val.whatsHappening();
}
...the problem you're having is val is of an unknown type. If T is CupThrower, then getObject() returns a CUP. Likewise, for MugThrower, getObject() returns a MUG. The way your code is written, you have no way to know the type returned by getObject() based solely on the type of T. So the solution is to add a way to know it. Try this:
class CupThrower{
public:
typedef CUP ObjectType;
ObjectType cp;
ObjectType getObject(){ return cp;}
};
class MugThrower{
public:
typedef MUG ObjectType;
ObjectType mg;
ObjectType getObject(){return mg;}
};
Now the type returned by getObject() is part of the enclosing class. You can change your whatsHappening() function to use this information:
template <typename T> void whatsHappening(T what){
T::ObjectType val = what.getObject(); //DOES COMPILE!
val.whatsHappening();
}
And all is right with the world again.
Auto is a feature only present in C++0x and, therefore, isn't enabled by default in most (if not all) the compilers. Have you used the appropriate options in your compiler to enable it?
It doesn't compile because you're trying to deal with zero-sized non-function objects.
Edit:
Works fine for me in VS2010.