1

Consider following types

template <typename T1, typename T2, typename T3>
struct either_or
{
    /* Here I need such an error type that says "Sorry, T1 is not an accepting type." */
    typdef error<T1> type;
};
template <typename T1, typename T3>
struct either_or <T1, T1, T3>
{
    typedef T1 type; //T1 Ok
};
template <typename T1, typename T2>
struct either_or <T1, T2, T1>
{
    typedef T1 type; //T1 Ok
};

/* Here is function that might accept error type variable */

template <typename T>
void foo(typename either_or<T, char, unsigned char>::type x)
{
    /*print char or unsigned char except that T is not printable*/
}

Is there an error type in type system of C++ to use in this case? If there isn't, can I realize it or how?

Yang
  • 777
  • 1
  • 10
  • 19
  • Sounds like you might want `std::enable_if` – Flexo Jul 09 '12 at 21:06
  • @Flexo Hmm...I've checked it as well as std::conditional and std::is_same in C++11. But I really need my function to tell explicitly that it stucks :-( – Yang Jul 09 '12 at 21:10

2 Answers2

4

No, there is no such type provided by the language or the standard library. You're welcome to make up your own, if you wish:

template <typename T>
struct error { };

Another option is to simply omit the type definition from the base template. When the values of T1, T2, and T3 don't match either of the two specializations, then you'll get the base template, which will have no type member. That will cause the compiler not to consider that version of foo, and you'll eventually get a compilation error when you try to call it with an invalid argument type.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467
  • So there is no way to make my function to tell that the type is acceptable or not right? – Yang Jul 09 '12 at 21:15
  • The compiler already tells you that. If it's acceptable, the compiler proceeds to compiler the rest of the program. If it's not acceptable, it says something like "There is no version of `foo` accepting that type." Some compilers will say what the acceptable types are, but that's usually when dealing with overloading, not templates. With overloading, there's a finite number of possibilities, so the compiler can print them all. With templates, it's harder to know what all possibilities are. This is a situation where good documentation would be easier than a technical solution. – Rob Kennedy Jul 09 '12 at 21:18
  • A trick sometimes used is to cause a little better error message like this typedef typename T1::____THIS_TYPE_DOES_NOT_WORK type; – Johan Lundberg Jul 09 '12 at 21:23
  • @Rob You are right. With MS VS2012 even intellisense can tell. Thanks. – Yang Jul 09 '12 at 21:23
1

How about:

template <typename T1, typename T2, typename T3>
struct either_or
{
    static_assert(false, "Sorry but this doesn't work for type T1");
    //typdef error<T1> type;
};
template <typename T1, typename T3>
struct either_or <T1, T1, T3>
{
    typedef T1 type; //T1 Ok
};
template <typename T1, typename T2>
struct either_or <T1, T2, T1>
{
    typedef T1 type; //T1 Ok
};

/* Here is function that might accept error type variable */

template <typename T>
void foo(typename either_or<T, char, unsigned char>::type x)
{
    /*print char or unsigned char except that T is not printable*/
}

This should display something like:

error: Sorry but this doesn't work for type T1
when instantiating either_or<T1,T2,T3>
with T1 = <typename>, T2=<typename>, T3=<typename>

if compiled - exact error message will depend on compiler of course. If you want to ask - no, it is not possible to integrate actual typename into message "Sorry but this doesn't work for type T1" - see this this thread.

Community
  • 1
  • 1
j_kubik
  • 6,062
  • 1
  • 23
  • 42