3

In my question type as returntype in c++ I was provided with an answer that gave me such a structure:

template <int N>
struct int_type {
    using type = std::conditional_t<N <= 8, std::uint8_t,
                 std::conditional_t<N <= 16, std::uint16_t,
                 std::conditional_t<N <= 32, std::uint32_t,
                 std::conditional_t<N <= 64, std::uint64_t,
                 std::uintmax_t>>>>;
};

That seemed to do excactly what I need, how ever the practice looks different, since I can't compile it because of the following errors:

...Error: expected nested-name-specifier before 'type'
 using type = std::conditional_t<N <= 8, std::uint8_t,
       ^
...Error: using-declaration for non-member at class scope
...Error: expected ';' before '=' token
 using type = std::conditional_t<N <= 8, std::uint8_t,
            ^
...Error: expected unqualified-id before '=' token

I tried to google it, but none of the posts I found seem to adress this specific problems. Can anyone explain me what is wrong with this code? I'm pretty new to C++

Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160
TreeOfLife
  • 123
  • 1
  • 7

3 Answers3

3

Your code is perfectly legal as long as your compiler supports stdlib's <type_traits> that define an alias template for std::conditional trait.

However, the error message clearly indicates you've not even enabled , therefore using is not parsed as an alias at all. To do that, add -std=c++11 or -std=c++14 option to your configuration.

If you can't, then in you can easily implement your own conditional trait:

template <bool B, typename T, typename F>
struct conditional
{
    typedef T type;
};

template <typename T, typename F>
struct conditional<false, T, F>
{
    typedef F type;
};

template <int N>
struct int_type {
    typedef typename conditional<N <= 8, uint8_t,
                 typename conditional<N <= 16, uint16_t,
                 typename conditional<N <= 32, uint32_t,
                 typename conditional<N <= 64, uint64_t,
                 uintmax_t>::type>::type>::type>::type type;
};

In you can use std::conditional instead of std::conditional_t, the only difference is that you need to access a nested typedef type on your own, which is a dependent name (typename keyword needed in front of a nested name specifier):

#include <cstdint>
#include <type_traits>

template <int N>
struct int_type {
    using type = typename std::conditional<N <= 8, std::uint8_t,
                 typename std::conditional<N <= 16, std::uint16_t,
                 typename std::conditional<N <= 32, std::uint32_t,
                 typename std::conditional<N <= 64, std::uint64_t,
                 std::uintmax_t>::type>::type>::type>::type;
};

In and , you need to include <cstdint> instead of <stdint.h>. The former guarantees the names are defined in the std namespace (the latter may define them only in the global namespace).

Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160
0

I'll add an answer here for the sake of completeness.

You need to #include <cstdint> and #include <type_traits>, then compile with C++14 support. Code:

#include <type_traits>
#include <cstdint>
#include <iostream>

template <int N>
struct int_type {
    using type = std::conditional_t<N <= 8, std::uint8_t,
                 std::conditional_t<N <= 16, std::uint16_t,
                 std::conditional_t<N <= 32, std::uint32_t,
                 std::conditional_t<N <= 64, std::uint64_t,
                 std::uintmax_t>>>>;
};

int main()
{
    int_type<10>::type t; // std::uint16_t
    t = 12;
    std::cout << t << std::endl;
}

Live example: http://coliru.stacked-crooked.com/a/9352f3349f48bff4

vsoftco
  • 55,410
  • 12
  • 139
  • 252
-1

Huh, when you do a typedef the compiler tells you what's wrong. Those are dependant typenames so you need a "typename" in front of it. so this should work:

#include <iostream>
#include <type_traits>
using namespace std;

template <int N>
struct int_type {
    using mytype = typename std::conditional<N <= 8, std::uint8_t,
                     typename std::conditional<N <= 16, std::uint16_t,
                       typename std::conditional<N <= 32, std::uint32_t,
                         typename std::conditional<N <= 64, std::uint64_t,
                           std::uintmax_t
                         >::type
                       >::type
                     >::type
                   >::type;
};
PeterT
  • 7,981
  • 1
  • 26
  • 34
  • 1
    `std::conditional_t` is not a typedef, but an alias template, it adds `typename` on its own in the definition – Piotr Skotnicki Dec 14 '14 at 15:58
  • @PiotrS. I mean that I wrote `typedef std::conditional<...> type;` and it showed a different error – PeterT Dec 14 '14 at 16:00
  • 1
    remove the first part of your answer then, nonetheless, the error doesn't indicate compiler's inability to resolve a dependent name, rather, missing support for aliasing – Piotr Skotnicki Dec 14 '14 at 16:01
  • @vsoftco I'm pretty sure they are dependent types, which is why the `conditional_t` alias uses `using conditional_t = typename conditional::type;`. You are correct that this is not the reason why OPs compilation failed and it's not really relevant to his question but those are dependent types. – PeterT Dec 14 '14 at 16:26
  • @PeterT ok, you are right, they are dependent, removed my comment, what I meant is that they belong to the current instantiation and do not need the `typename` qualifier, as the compiler is not confused between a type and an eventual variable declaration. See e.g. http://en.cppreference.com/w/cpp/language/dependent_name near the bottom, where some examples are given about the usage of `typename`. – vsoftco Dec 14 '14 at 16:29