dimanche 2 août 2015

How to correctly read the template partial specialization?

Suppose the following declaration:

template <typename T> struct MyTemplate;

The following definition of the partial specialization seems to use the same letter T to refer to different types.

template <typename T> struct MyTemplate<T*> {};

For example, let's take a concrete instantiation:

MyTemplate<int *> c;

Now, T in template <typename T> is int *. However, T in MyTemplate<T*> is int!

How is the definition of the partial specialization read correctly?

C++ class name injection

According to the standard [class]/2:

… The class-name is also inserted into the scope of the class itself; this is known as the injected-class-name.…

Moreover, [basic.scope.pdecl]/9:

The point of declaration for an injected-class-name (Clause 9) is immediately following the opening brace of the class definition.

Finally, [basic.lookup.classref]/3 and its example:

If the unqualified-id is ~ type-name, the type-name is looked up …

struct A { };
struct B {
    struct A { };
    void f(::A* a);
};
void B::f(::A* a) {
    a-> ~ A(); // OK: lookup in *a finds the injected-class-name
}

So far, we can gather:

  1. In the scope of a class A, there exists a name A.
  2. That name is declared at the opening of the definition brace of class A.
  3. That name names a type.

If the above is correct, then why does the following code fails to compile (in MSVC2015):

struct inj
{};

typedef struct inj::inj inj2;

The error message

Error C2039 '{ctor}': is not a member of 'inj'

seems to be at odds with the standard:

Note: For example, the constructor is not an acceptable lookup result in an elaborated-type-specifier so the constructor would not be used in place of the injected-class-name. —end note

A template that accepts only pointer type arguments

After seeing that a template can be partially specialized for reference or pointer types, I was wondering whether I can write a template that accepts only a pointer type to start with. This is my attempt:

template <typename T*>
struct MyTemplate{};

int main() {
    MyTemplate<int *> c;
    (void)c;
    return 0;
}

This does not compile. How should it be modified? (i.e. if what I am trying to accomplish is at all possible)

samedi 1 août 2015

C++ list iterator arithmetic

I am aware that you cannot use iterators with list in the form "it +n" but why is that when I use ++it the program is able to compile i.e:

//program compiles
auto begin = v.begin(),
end = v.end(); 
while (begin != end) {
    ++begin;  
    begin = v.insert(begin, 42); 
    ++begin;  // advance begin past the element we just added
}

//program doesn't compile
auto begin = v.begin(),
end = v.end(); 
while (begin != end) {
    begin+=1;  
    begin = v.insert(begin, 42);  // insert the new value
    ++begin;  // advance begin past the element we just added
}

Howto check that all types in variadic template are convertible to size_t?

How can I check that all types in a variadic template declaration can be converted to size_t:

// instantiate only if extents params are all convertible to size_t
template<typename T, size_t N>
template<typename... E>
Array<T,N>::Array(E... extents) {
    constexpr size_t n = sizeof...(extents);
    static_assert(n == N, "Dimensions do not match");
    // code for handling variadic template parameters corresponding to dimension sizes
}

With the following usage:

Array<double, 2> a(5,6);    // OK 2-D array of 5*6 values of doubles.
Array<int, 3> a(2,10,15)    // OK 3-D array of 2*10*15 values of int.
Array<int, 2> a(2, "d")     // Error: "d" is not a valid dimension and cannot be implicitly converted to size_t 

Here are similar questions: Check for arguments type in a variadic template declaration

Passing multiple parameter packs treated as non-pack parameter?

In trying to write a simple example for currying of metafunction classes, I wrote the following:

#include <type_traits>

struct first {
    template <typename T, typename U>
    using apply = T;
};

template <typename C, typename... Args>
struct curry {
    struct type {
        template <typename... OtherArgs>
        using apply = typename C::template apply<Args..., OtherArgs...>;
    };
};

int main() {
    static_assert(std::is_same<first::apply<int, char>, int>::value, ""); // OK

    using AlwaysInt = curry<first, int>::type;
    static_assert(std::is_same<AlwaysInt::apply<char>, int>::value, ""); // error
}

The second static_assert fails to compile on both gcc 5.1:

main.cpp:17:72: error: pack expansion argument for non-pack parameter 'U' of alias template 'template<class T, class U> using apply = T'
         using apply = typename C::template apply<Args..., OtherArgs...>;
                                                                        ^

and clang 3.6:

main.cpp:17:59: error: pack expansion used as argument for non-pack parameter of alias template
        using apply = typename C::template apply<Args..., OtherArgs...>;
                                                          ^~~~~~~~~~~~

Same error in both cases. However, if I outsource the application in curry to a separate metafunction:

template <typename C, typename... Args>
struct eval {
    using type = typename C::template apply<Args...>;
};

template <typename C, typename... Args>
struct curry {
    struct type {
        template <typename... OtherArgs>
        using apply = typename eval<C, Args..., OtherArgs...>::type;
    };
};

Both compilers compile just fine. Is there something wrong with the original example or is this just a bug in both compilers?

How to obtain cached 'A' records from local DNS client?

I am trying to obtain the cached "A" records from my DNS client. "ipconfig /displaydns" shows everything but I am interested in retrieving "A" records. I've found the following code from here: But it only shows the domain name. What do I need do add to this code to obtain the the IP addresses?

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <WinDNS.h>
#include <stdarg.h>
typedef struct _DNS_CACHE_ENTRY {
struct _DNS_CACHE_ENTRY* pNext; // Pointer to next entry
PWSTR pszName; // DNS Record Name
unsigned short wType; // DNS Record Type
unsigned short wDataLength; // Not referenced
unsigned long dwFlags; // DNS Record FlagsB
} DNSCACHEENTRY, *PDNSCACHEENTRY;

typedef int(WINAPI *DNS_GET_CACHE_DATA_TABLE)(PDNSCACHEENTRY);

int main(int argc, char **argv) {

PDNSCACHEENTRY pEntry = (PDNSCACHEENTRY) malloc(sizeof(DNSCACHEENTRY));
// Loading DLL
HINSTANCE hLib = LoadLibrary(TEXT("DNSAPI.dll"))
// Get function address
DNS_GET_CACHE_DATA_TABLE DnsGetCacheDataTable =
    (DNS_GET_CACHE_DATA_TABLE) GetProcAddress(hLib, "DnsGetCacheDataTable");
int stat = DnsGetCacheDataTable(pEntry);
printf("stat = %d\n", stat);
pEntry = pEntry->pNext;
while (pEntry) {
    wprintf(L"%s : %d \n", (pEntry->pszName), (pEntry->wType));
    pEntry = pEntry->pNext;
}
free(pEntry);
return 0;
}