1

I have a templated class and a type that depends on the template. How can I use this type in my .cpp file?

object.hpp:

using pair_d = std::pair<double, double>;
using pair_f = std::pair<float, float>;

template <typename T>
class Object {
    public:
        static_assert(std::is_same<T, float>::value ||
                      std::is_same<T, double>::value, "Type not allowed");

        using pair = typename std::conditional<std::is_same<T, float>::value,
                     pair_f, pair_d>::type;

        // function using the conditional type
        const pair doSomething(T, T) const;
}

object.cpp

#include "object.hpp"

template <typename T>
const pair Object<T>::doSomething(T t1, T t2) const {
    // ....
}

But the I get:

error: unknown type name 'pair'

How can I use the type 'pair' in my .cpp file?

gartenriese
  • 4,131
  • 6
  • 36
  • 60

3 Answers3

3

You'll need to qualify the name if you use it before the Object<T> part.

template <typename T>
typename Object<T>::pair Object<T>::doSomething(T t, T t) const {
    // ....
}
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
3

There are four issues in your snippet:

  1. The arguments are named with the same name (T t, T t), make those names different.

  2. You have split the template declaration/definition into a cpp and a header file, don't do that.

  3. You forgot about a const qualifier on a return type in the definition (which is in the declaration).

  4. You are missing a typename keyword for a dependent name.

Your definition should be:

template <typename T>
const typename Object<T>::pair Object<T>::doSomething(T t1, T t2) const {
    // stuff
}

or (to avoid a dependent name):

template <typename T>
auto Object<T>::doSomething(T t1, T t2) const -> const pair {
    // stuff
}
Piotr Skotnicki
  • 46,953
  • 7
  • 118
  • 160
  • I fixed 1 and 3, thanks. I want to split declaration and definition because the definitions are pretty long. That would not look good in the header file. – gartenriese Oct 08 '14 at 14:03
  • 1
    @gartenriese: your solution would not work at all, see http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – Piotr Skotnicki Oct 08 '14 at 14:04
0

Why do you need this?

using pair = typename std::conditional<std::is_same<T, float>::value,
                     pair_f, pair_d>::type;

Why not just:

typedef std::pair<T,T> pair;

Unless you need two template type arguments. Even if you need two type arguments, use them directly.

I didn't say don't use static_assert!

Ajay
  • 18,086
  • 12
  • 59
  • 105
  • Do I not have the same problem when using a typedef? – gartenriese Oct 08 '14 at 19:31
  • No. You cannot implement a class template in CPP file (as a translation unit). Templates are compiled using 2 phase compilation process. Second phase would come only on template instantiation, which won't cause CPP file's 2nd phase compilation. – Ajay Oct 09 '14 at 04:16