The subclass insists on calling the template, not the constructor

The following does not compile with g ++ 4.4.7, with -std == C ++ 0x passed on the command line:

#include <algorithm>
#include <iostream>

template <typename T>
class A
{
public:
    T v;

    A() { std::cout << "A default constructor\n"; }
    A(const A& i): v(i.v) { std::cout << "A copy constructor\n"; }
    A(A&& i): v(std::move(i.v)) { std::cout << "A move constructor\n"; }
#if 1 // turn this off to fix the version without static_cast
    template <typename V>
    explicit A(const V& i): v(i) {}
#endif
};

class B: public A<int>
{
public:
    B() { std::cout << "B default constructor\n"; }
#if 1 // turn this off to get static_cast that makes it compile
    B(const B& i): A<int>(i) {
        std::cout << "B copy constructor\n"; }
    B(B&& i): A<int>(std::move(i)) {
        std::cout << "B move constructor\n"; }
#else
    B(const B& i): A<int>(static_cast<const A<int> &>(i)) {
        std::cout << "B copy constructor\n"; }
    B(B&& i): A<int>(std::move(static_cast<A<int> &&>(i))) {
        std::cout << "B move constructor\n"; }
#endif
};

B foo() {
    B t;
    return t;
}

int main() {
    B t(foo());
    B t2(std::move(t));
    std::cout << "Result is " << t2.v << std::endl;
    return 0;
}

It throws the following error, where apparently the copy and move constructors cause an explicit pattern A, rather than the obvious copy / move constructors A:

container.cpp: In constructorA<T>::A(const V&) [with V = B, T = int]’:
container.cpp:26:   instantiated from here
container.cpp:17: error: cannot convertconst Btointin initialization

Disabling the first one #if 1deletes the template, and it compiles and produces the expected calls. Disabling the second #if 1also makes it work (however, doing the equivalent in our code would be painful and would require a lot of careful editing).

I currently get around this by changing the template constructor to this and adding a bool for all users, but this is ugly:

A(const V&i, bool dummy): v(i) {}

Questions:

  • Is this a bug in GCC?
  • If not, can someone explain why this is happening?
  • ? static_casts?
+4
1

, , A, / A:

A(A const&): A B const&, ( ), A(A const&), ( ).

, , . , , A ( SFINAE):

template <typename V>
explicit A(const V& i,
           typename std::enable_if<! std::is_base_of<A, V>::value>::type* = nullptr)
    : v(i) {}

(!)

+5

All Articles