Martin's Tex-Blog

Posts on programming and generally technical topics

Archive for the ‘C++’ Category

Simple introduction of SFINAE use to fix overloading issues when using forwarding references.

leave a comment »


You have probably read on it in stackoverflow answer, or maybe one of your friends have given you an advice to “SFINAE away those overloads” to fix the overload resolution problems. The SFINAE stands for Substitution Failure Is Not An Error, and in that form is present in the C++ standard. Without this concept it would not be possible to choose correct overloads, consider this example:

http://coliru.stacked-crooked.com/a/79ec2049db08566a

//#1
template<typename T> typename T::value_type foo(T t) {
    // accepts types containing type member of name value_type
    std::cout << "typename T::value_type foo(T t)\n";
    return typename T::value_type{};
}
//#2
int foo(int t) {
    std::cout << "int foo(int t)\n";
    return 0;
}

int main()
{
    foo(1);
    foo(std::vector<int>{});
}

using overload #1 with int type is obviously an error (there is not such thing as int::value_type), but when compiler considers this overload it does not issue an error but only removes this candidate from the list of valid overloads. This is substitution failure is not an error rule in action.

Now lets go back to the topic, with C++11 we have whats called forwarding references, which allow function templates to bind to nearly all types and pass them further. The problem is that they are quite greedy monsters and when you want to overload them with some other types, there is a great chance the overloads will not get called. One of the solutions to this problem is to use tag dispatch. Example on how to use it is presented in below code.

First I present the problem when, greedy eat_all_monster template function with forwarding reference, takes it all. Even thought you would like eat_all_monster(1) to call float overload, it will not happen.

Then there is a code which assigns a type tag to each group of types assigned to specified function overloads. This way you have full control over which overload should be called for which type.

http://coliru.stacked-crooked.com/a/e13dee36eb479174

#include <iostream>
#include <string>
#include <type_traits>

// Version without tag dispatch, shows that for certain types universal 
// reference function overload will steal all calls.
template<typename T>
void eat_all_monster(T&& t) {
    std::cout << t << ", void eat_all_monster(T&& t)\n";
}

void eat_all_monster(float f) {
    std::cout << f << ", void eat_all_monster(float f)\n";
}

void eat_all_monster(const std::string& s) {
    std::cout << s << ", void eat_all_monster(std::string t)\n";
}

void test1() {
   int n = 101;
    std::string s = "123";
    eat_all_monster(n);
    eat_all_monster(s);
    eat_all_monster("12345");
    
    // Above will all call universal reference version of eat_all_monster. 
    // No special overloads will get called.
    //
    // 01, void eat_all_monster(T&& t)
    // 123, void eat_all_monster(T&& t)
    // 12345, void eat_all_monster(T&& t)    
}

// Now, to fix it we will use tag dispatch.

// This is a general tag.
using tag_for_all = std::integral_constant<int, 0>;

// Now, a tag for values, integers, shorts, floats etc.
using tag_for_values = std::integral_constant<int, 1>;

// Tag for texts, const char*, char arrays, std::string
using tag_for_texts = std::integral_constant<int, 2>;

// General trait, will catch all non values, or non texts
template<typename T> struct eat_trait { using tag = tag_for_all; };

// Below two are for specialization for which we have special overloads
template<> struct eat_trait<float>       {    using tag = tag_for_values; };
template<> struct eat_trait<int>         {    using tag = tag_for_values; };
template<> struct eat_trait<std::string> { using tag = tag_for_texts; };
template<> struct eat_trait<const char*> { using tag = tag_for_texts; };

template<typename T>
void eat_some_monster_impl(T&& t, tag_for_all) {
    std::cout << t << ", void eat_some_monster_impl(T&& t)\n";
}

void eat_some_monster_impl(float f, tag_for_values) {
    std::cout << f << ", void eat_some_monster_impl(float f)\n";
}

void eat_some_monster_impl(const std::string& s, tag_for_texts) {
    std::cout << s << ", void eat_some_monster_impl(std::string t)\n";
}

template<typename T>
void eat_some_monster(T&& t) {
    // decay_t is needed because for lvalue-s, T will be a reference (T&), 
    //         and float& and float are two different types
    //         Actually it strips references, cv-qualifications 
    //         (const volatile), and also turns char array to 
    //         pointer to char.
    eat_some_monster_impl(std::forward<T>(t), 
        typename eat_trait<std::decay_t<T>>::tag{});
}

void test2() {
    int n = 101;
    std::string s = "123";
    
    // Now version with tag dispatch will choose the appropriate 
    // overloads based on tags from type traits.
    std::cout << "\n";
    eat_some_monster(n);        // calls value overload (tag_for_values)
                                //  which accepts all values as float
    eat_some_monster(1.0f);     // -- // --
    eat_some_monster(s);        // calls text overload (tag_for_texts) 
                                //  which accepts all texts as std::string 
                                //  (they will convert to it)
    eat_some_monster("12345");  // -- // --
    eat_some_monster((void*)0x1234); // No special overload for void*, so 
                                     //  general version will be called with 
                                     //  tag: tag_for_all    
    
    /*
    // Output is exactly as expected:
    101, void eat_some_monster_impl(float f)
    1, void eat_some_monster_impl(float f)
    123, void eat_some_monster_impl(std::string t)
    12345, void eat_some_monster_impl(std::string t)
    0x1234, void eat_some_monster_impl(T&& t)
    */
}

int main()
{
    test1();
    test2();
}

Advertisement

Written by Marcin

March 14, 2017 at 1:04 am

Posted in C++

Platform dependend overload resolution ambiguity

leave a comment »


Here I will show case when types used internally by compiler might cause ambiguities in overload resolution. Below is example code:

#include <string>
struct CoolString {
    std::string s;
    CoolString(const char* p) : s(p){}
    char& operator[](size_t i) { return s.at(i); }
   operator char*() { return &s[0]; }
};

int main()  {
    CoolString ss("asd");
    ss[1] = '1';  // {1}
}
  

It looks valid, althought use of implicit user conversion operator to char* is a sign of bad design (std::string provides c_str instead). Above code compiles under g++ and clang, but fails to compile under Visual Studio. The error is that call {1} is ambiguous, and looks like below:

2>c:\prj\test.cpp(10) : error C2666: 'CoolString::operator []' : 2 overloads have similar conversions
2>        c:\prj\test.cpp(10): could be 'char &CoolString::operator [](size_t)'
2>        or 'built-in C++ operator[(char *, int)'
2>        while trying to match the argument list '(CoolString, int)'

so, compiler is unable to decide which one of those to choose:

ss.operator[](1) // line 1
ss.operator char*()[1] // line 2

In case of second choice ( line 2 ), compiler wants to apply built in subscript operator after user defined conversion to char*. Built in subscript operator takes index as a ptrdiff_t type. Because this is a typedef, lets check how it differs under g++/clang from VS:

std::cout << "size_t = " << typeid(size_t).name() << std::endl; // VS2013: unsigned int, g++: unsigned long
std::cout << "ptrdiff_t = " << typeid(ptrdiff_t).name() << std::endl; // VS2013: int, g++: long

Under VS ptrdiff_t is int, while under g++/clang its long. While size_t is always unsigned. Lets look what conversions are required by both candidates:

ss.operator[](1) – here only integral promotion of int to unsigned int or unsigned long is required

ss.operator char*()[1] – here on VS only user defined conversion must be applied to ss (so that operator char*() is called), since 1 is an int it matches ptrdiff_t which under VS is also int. But under g++/clang two conversions are requried: first user defined to char*, and then promotion of int to long.

Now its clear why VS shows error, implicit conversions sequences are ambiguous – both are of same lenghts, also they differ on different positions, but I am not clear about it here (exact standard wording) – you could argue that integral promotion should be more promoted than user defined conversion.

Under g++/clang built in operator is not choosen because it requires two implicit conversions, first is user defined conversion, second is promotion int to long. So compiler choses ss.operator[](1) which requires only integral promotion.

The solution is to:
1. Dont use implicit conversion operator to char*
2. Replace size_t with int in char& operator[](size_t i), this will make it a perfect match and top priority candidate.
3. Use ss[1u]

For more references:
http://stackoverflow.com/questions/1726740/c-error-operator-2-overloads-have-similar-conversions
– “C++ Templates – The Complete Guide” – B.2.1

Written by Marcin

January 17, 2015 at 3:10 am

Posted in C++, Uncategorized

Friend definition – or friend functions defined inside class body

leave a comment »


This is a slightly less known feature of C++ which allows you to define a function that can be called only by using Argument Dependent Lookup (ADL). Compiler will create non-member function in the namespace surrounding class where it is defined. This is how it looks like:

namespace Forest {
class CTree {
public:
CTree(int) {}

// This parameter less foo function is actually unaccessible
friend void foo() {}

// This one is accessibly only through ADL
friend void foo(const CTree&) {}
};
}

Forest::CTree tree(0);
foo(tree); // ok - call by ADT
//foo(); // error
//foo(0); // error - foo is not considered as candidate using ADL due to required implicit conversion
//Forest:foo(); // error
//Forest::foo(tree); // error
//Forest::foo(); // error

So, how is that usefull to us? It allows you to call a foo function without qualifying it with namespace name. It makes greater sense in case of operator definitions. If you define operator== as a friend inside class body, then it will get called only by ADL – as it should, and it will also have full access to your class private data. Coders mostly define binary operators as a free function to allow for implicit conversions of arguments. The problem with friend defined operator is that implicit conversion will not happen.

references:
http://stackoverflow.com/questions/8207633/whats-the-scope-of-inline-friend-functions
http://stackoverflow.com/questions/381164/friend-and-inline-method-whats-the-point

Written by Marcin

January 11, 2015 at 1:08 am

Posted in C++

Implicit type conversions with templates

leave a comment »


Suppose you want to write a template class X that must allow for operations like X = X + Y or X = Y + X, where Y is any type like int, float or other class type. How you want to start with that? Normally you would write operator+ as a free function and add it as a friend to X. Lets assume we want Y to be an int. Below code seems to solve this scenario:

template<typename T>
class X {
public:
  int n;
  X(int rn) : n(rn) {}
  template<class U>
  friend X<U> operator+(const X<U>& lhs, const X<U>& rhs);
};

template<typename U> 
  X<U> operator+(const X<U>& lhs, const X<U>& rhs) {
    X<U> ret(0);
    ret.n = lhs.n + rhs.n;
    return ret;
  }

int main() {
  X<int> a = 1;
  X<int> b = 2;
  X<int> c = a + b;
  c = c + 1;
  c = 1 + c;
  std::cout << "X : " << c.n << std::endl;
}

unfortunately this will result in errors (compilation using clang):

source_file.cpp:25:7: error: invalid operands to binary expression ('X<int>' and 'int')
c = c + 1;
    ~ ^ ~
source_file.cpp:15:7: note: candidate template ignored: could not match 'X<type-parameter-0-0>' against 'int'
X<U>& operator+(const X<U>& lhs, const X<U>& rhs) {
      ^
...

the problem is that template operator+ is not considered as a valid overload. In case of function templates, compiler will perform type deduction on the arguments and come up with a template parameter types that will match the call or else it will remove such function from list of potential candidates. Whats important here is that no implicit conversions will be done. So to make above code compile we would have to change class usage to:

c = c + X<int>(1);
c = X<int>(1) + c;

this way, there is no need for implicit conversion using X(int rn) constructor. But this is not what we want. The solution is to use a language feature that enables you to define a non-member friend function inside template class definition, as in the following example:

template<typename T>
class X {
public:
int n;
X(int rn) : n(rn) {}

friend X operator+(const X& lhs, const X& rhs) {
    X ret(0);
    ret.n = lhs.n + rhs.n;
    return ret;
}

};

int main() {
  X<int> a = 1;
  X<int> b = 2;
  X<int> c = a + b;
  c = c + 1;
  c = 1 + c;
  std::cout << "X : " << c.n << std::endl;
}

Now this compiles and outputs X: 5. Lets analyse what friend X operator+(const X& lhs, const X& rhs) means. First, X is the same as X<T>, due to class name injection (within the scope of a class template X with template parameters P1, P2, … the name of that template (X) can be equivalent to the template-id X<P1, P2, …>). Second thing is that compiler will generate for any used template parameter type a free non-template function at namespace level (outside of class X) which will be used during normal function call. Whats important for us here is that compiler will perform implicit conversions on its arguments. Such functions will be generated always, even if not used by given class instantiation. Below is example of such compiler generated free function:

X<int> operator+(const X<int>& lhs, const X<int>& rhs) {
    X<int> ret(0);
    ret.n = lhs.n + rhs.n;
    return ret;
}

This is not a new feature in C++, I suppose its c++98 wording is easier to understand.

C++98 [temp.friend]p5: When a function is defined in a friend function declaration in a class template, 
the function is defined at each instantiation of the class template. The function is defined even if it is never used.

C++11 [temp.friend]p4: When a function is defined in a friend function declaration in a class template, 
the function is instantiated when the function is odr-used. The same restrictions on multiple declarations
and definitions that apply to non-template function declarations and definitions also apply to these implicit definitions.

Written by Marcin

January 3, 2015 at 2:54 am

Posted in C++

Default template parameter redeclaration

leave a comment »


[temp.param]/12 Clearly states :

A template-parameter shall not be given default arguments by two different declarations in the same scope.

now, both clang and g++ generates errors for following code:

template<class T = int> class X;
template<class T = int> class X {};

msvc on the other hand (even with no extensions enabled) compiles it fine, I had to change second default parameter from int to some other type to see error. So its not that really bad, but still ‘shall not’ means ‘is not allowed’ as per ISO/IEC Directives. msvc on the other hand gives error in similar case but with redeclaration of function default parameter values.

Written by Marcin

December 31, 2014 at 12:17 am

Posted in C++

String literal as non type template parameter

leave a comment »


Unfortunately it is not possible to have template with string literal as a non type parameter. Until C++11 reason was that string literals had internal linkage, while non type template parameters allowed only external linkage pointers. It makes sense because templ_class should have the same typeid in all translation units. It kind of could work with string pooling enabled – which is availabe for both gcc and msvc. After C++11 the reason is more of that string literals does not match any of the allowed entities as template parameter.

You can use character array initialized with string literal as non type parameter. It compiles both with g++ and msvc:

#include <typeinfo>

template<const char* STR>
class MyStr {};

extern const char my_string[]; const char my_string[] = "alfabet";
extern const char my_string2[]; const char my_string2[] = "alfabet";

// or use constexpr
//constexpr const char my_string[] = "alfabet";
//constexpr const char my_string2[] = "alfabet";

extern const char* my_string_pc;
const char* my_string_pc = "alfabet";

int main(){
   
    // This fails with:
    //  main.cpp:30:31: error: 'my_string_pc' is not a valid template argument because 'my_string_pc' is a variable, not the address of a variable
    //    typedef MyStr<my_string_pc> str_type3;
    typedef MyStr<my_string_pc> str_type3;     
   
    // Below compiles, but gives different types
    typedef MyStr<my_string> str_type1;   
    typedef MyStr<my_string2> str_type2; 
   
    // This fails
    static_assert(std::is_same<str_type1, str_type2>::value, "");
   
    return 0;
}

EDIT:
After writing it I have found in standard ([temp.arg.nontype]) the actual reasoning for all above:

[ Note: A string literal (2.14.5) does not satisfy the requirements of any of these categories and thus is not
an acceptable template-argument. [ Example:

template<class T, const char* p> class X {
/ ... /
};
X<int, "Studebaker"> x1; // error: string literal as template-argument
const char p[] = "Vivisectionist";
X<int,p> x2; // OK

—end example ] —end note ]

refs:
http://stackoverflow.com/questions/5547852/string-literals-not-allowed-as-non-type-template-parameters

Written by Marcin

December 30, 2014 at 12:56 am

Posted in C++, Uncategorized

Dependent base class name lookup (c++ template complete guide)

leave a comment »


If you were reading c++ template complete guide : “5.2 using this->” you probably tried to test following example:

template<typename T>
class Base {
public:
  void exit() {}
};

template<typename T>
class Derived : public Base < T > {
public:
	void callMe() {
	  exit();
	}
};

if you done it under Visual Studio, you have probably realized that it does compile with no errors or warnings, so what is going on here. Your next step should be to test it with gcc or clang compiler, you would see errors now.

The problem is that VS does not implement two phase name lookup. I have found that in VS2013 diabling language extensions with /Za actually causes above code to fail to compile.

some usefull links below
http://blog.llvm.org/2009/12/dreaded-two-phase-name-lookup.html
http://stackoverflow.com/questions/11405/gcc-problem-using-a-member-of-a-base-class-that-depends-on-a-template-argument
http://clang.llvm.org/compatibility.html#dep_lookup_bases

Written by Marcin

December 16, 2014 at 11:24 am

Posted in C++

shared_ptr and aliasing constructor

leave a comment »


shared_ptr seems to be straightforward class, but if you look closer you will find aliasing constructor that make you think – what the hell is that?

template<class Y>
shared_ptr( const shared_ptr<Y>& r, T *ptr );

The idea of this constructor is to keep reference count of owned object – r, while using pointer of some other stored object (mostly field in r object). This means that shared_ptr is allowed to own one object and store some other raw pointer. Only owned object is reference counted, while stored pointer is the one that gets returned during dereferencing. In normal situation, when aliasing constructor is not used, raw pointer is the one for owned object.

Below is example of aliasing constructor usage, where stored pointer is contained inside owned one:

#include <iostream>
#include <memory>

struct Data {
	int d;
};

int main(int argc, char* argv[])
{
	std::shared_ptr<Data> pd(new Data());
	std::shared_ptr<int> pd_d(pd, &pd->d); //pd is owned object, while &pd->d is stored (retuned on dereference)

	*pd_d = 10; 

	std::cout << pd.use_count() << std::endl; // outputs 2
	pd_d.reset();
	std::cout << pd.use_count() << std::endl; // outputs 1
	pd.reset();
	std::cout << pd.use_count() << std::endl; // outputs 0

	// pd->d is now a dangling pointer, dont use it!

	return 0;
}

Other use is for making shared_ptr of derived type:

        struct Base {
	  virtual ~Base(){}
        };
        struct Derived : public Base {
	  void foo() {}
        };

	std::shared_ptr<Base> pd_base(new Derived());
	std::shared_ptr<Derived> pd_derived(pd_base, dynamic_cast<Derived*>(pd_base.get()));
	pd_derived->foo();

Other use case for aliasing constructor is when you are using interface that requires shared_ptr but you dont want it to keep ownership of your object. In such case you can make shared_ptr to work like normal bare pointer:

    static Data globalData;
    std::shared_ptr pd2(std::shared_ptr(), &globalData.d);
    std::cout << pd2.use_count() << std::endl; // outputs 0, but *pd is valid
    *pd2 = 2;

Aliasing constructor is not forcing you to keep pointer as a stored object, it can be any type of size_t. When you realize this you can use this constructor also for keeping timestamp in some caching mechanism. For further info look here:

http://www.codesynthesis.com/~boris/blog/2012/04/25/shared-ptr-aliasing-constructor/

Other uses are: refering to container element (owned object is container, stored pointer is element in container), referring to a shared library symbol.

What you should not do:

	std::shared_ptr pd(new Data());
	std::shared_ptr pd_d(pd, new int()); // here new int() is an error, this pointer will never be freed.

Written by Marcin

November 15, 2014 at 5:19 pm

Posted in C++

rvalue, lvalue, prvalue, xvalue, glvalue – what are those?

leave a comment »


Previous standard C++03 divided expressions into lvalues and rvalues, new standard C++11 adds three more categories: xvalue, glvalue and prvalue. What are those and why we need them all?

Lets start with lvalues and rvalues.

The common definition for lvalue is a non-const object that may be put on the left hand side of assignment. It can be an expression or function.

rvalue on the other hand is an expression that cannot be placed on the left hand side of assignment, it provides only value and cannot be assigned to.

For example:

int lvalue;
lvalue = 1;         // 1*
(lvalue + 10) = 1;  // 2* - error

char arr[15];
*(arr + 3) = 'a' ; // 3*

int& lvalueRetFunc(int& v) { return v; }
int rvalueRetFunc(int v) { return v; }
lvalueRetFunc(lvalue) = 10; // 4*
rvalueRetFunc(lvalue) = 10; // 5* - error

1* – here we have proper assignment to lvalue
2* – here we have an expression (lvalue + 10) that denotes rvalue which cannot be assigned, in VS C++ 2010 this code will produce following error “error C2106: ‘=’ : left operand must be l-value”.
3* – example of expression that yields lvalue
4* – here we have a function returning lvalue which can be assigned
5* – here function returns rvalue which cannot be assigned and results in the same error like in 2*

From those examples it is easy to see that lvalue can be used where rvalue is required, but not the other way around, rvalue cannot be used in place of lvalue with the exception when c++11 new construct – rvalue reference is used.

Fundamental property of lvalue is that it has a location. This location can be used in assignment expressions, you can use lvalue to take its address.

lvalues are also said to be persistent, rvalues on the other hand are temporary, or ephemeral and are available only until end of full expression, but if rvalue it assigned to const reference or pointer then its lifetime will be prolonged.

lvalues not always can be modified, for example when they are const variables or array types.

Now lets introduce xvalue, glvalue and prvalue. With C++11 comes new language feature called rvalue references. It allows to steal internals of rvalues and use them in constructing new objects that can be later on used as lvalues. This was actually possible in C++03 but was largely complicated. Those three new expression categories were introduced to properly describe this new language feature.

Xvalue (eXpiring value) is the most important new concept, it is tightly connected to new move semantics. To shortly describe move semantics, lets see an example:

In C++03 you would initialize class object with string as follows:

class MyData {
std::string s;
public:
  MyData(std::string ss)
   :  s(ss) // (2*) here creates another allocation and copy
  {}
};

MyData md("mydata"); // (1*) creates one temporary which requires at least one allocation

The problem is that it introduces temporary rvalues that allocate memory and also do some other operations. With C++11 comes possibility to actually “steal” inner contents from such temporary in (2*) and eliminate not needed allocations/operations:

class MyData {
std::string s;
public:
  MyData(std::string ss) : s(std::move(ss)) {} // here no allocations are created, inner guts of temporary ss are used to initialize s variable
};

MyData md("mydata"); // here creates temporary string object

Xvalue in the second example is the std::move(ss) experssion, it returns rvalue reference which is an indication to std::string class that we want to steal inner contents from this temporary and use it in s variable. What std::move really do is to turn named variable into unnamed reference, this is an indication to compiler that we really know what we are doing, and we want s variable to be constructed from ss using move semantics. So the new name for such expression was needed, since move semantics in this example is explicit – without std::move we are back in C++03 world.

After that ss in MyData() constructor is actually empty, standard guarantees that such objects are in a “valid but unspecified state”, that means you can assign new values to it, but current value is not defined.

So – since C++11 rvalue got new semantic which is being an rvalue reference – this means that besides its old semantic it can also behave as xvalue described above.

Now to those two last names:
– when you see prvalue (“pure” rvalues) – this indicated plain old rvalues from C++03. Those are not xvalues.
glvalue (“generalized” lvalue) is just a grouping for lvalues and xvalues.

[refs]
http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3055.pdf

Written by Marcin

October 8, 2012 at 2:09 am

Posted in C++