wyer33
wyer33

Reputation: 6340

Does template specialization work with alias templates?

Does template specialization work with alias templates? Specifically, the following code throws an unexpected error:

$ cat test01.h 
#ifndef TEST01_H
#define TEST01_H

#include <iostream>
#include <typeinfo>
#include <cstdlib>

template <template <typename> class Ops>
double add1(double const & x) {
    std::cerr << "Undefined for type: " << typeid(Ops <double>).name() << std::endl;
    exit(EXIT_FAILURE);
}

template <typename Real>
struct MyOps {
    static Real add(Real const & x,Real const & y) {
        return x+y;
    }
};

template <typename Real> using MyOpsAlias = MyOps <Real>;

#endif

In addition,

$ cat test01.cpp 
#include "test01.h"

template <>
double add1 <MyOps> (double const & x) {
    return MyOps <double>::add(x,1.);
}

int main() {
    std::cout << add1 <MyOps> (2.) << std::endl;
    std::cout << add1 <MyOpsAlias> (2.) << std::endl;
}

After running this code, I receive

$ ./test01 
3
Undefined for type: 5MyOpsIdE

I expected that both answers should return 3 since MyOpsAlias should just be an alias template of MyOps. In case it matters, I'm using GCC 4.7.3.

Upvotes: 1

Views: 93

Answers (2)

Constructor
Constructor

Reputation: 7473

As Johannes Schaub - litb explains in his answer to my recent question:

A alias template is not a template alias (despite intended by some to be).

So it is not a bug, it is a standard-compliant behavior.

See also paragraph [temp.alias] 14.5.7/2 of the standard:

[ Note: An alias template name is never deduced. — end note ]

Upvotes: 1

Jarod42
Jarod42

Reputation: 217135

You may do the following:

namespace detail
{

template <typename T> struct Adder
{
    double operator() (double) const {
        std::cerr << "Undefined for type: " << typeid(T).name() << std::endl;
        exit(EXIT_FAILURE);
    }
};

template <typename T> struct Adder<MyOps<T>>
{
    double operator() (double x) const {
        return MyOps<T>::add(x, 1.);
    }
};

}

template <template <typename> class T>
double add1(double const & x) {
    return detail::Adder<T<double>>()(x);
}

Upvotes: 0

Related Questions