Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

The code below fails to compile with gcc 7.1.0, which complains about providing the wrong number of template arguments in the second line of main. This version of GCC is supposed to implement template argument deduction of class templates.

I think the compiler should be able to deduce the class template argument T2 for Bar, which means that I shouldn't have to explicitly specify both arguments (Bar<int, int>) given paragraph 17.8.1.3 of the C++17 draft which says, "Trailing template arguments that can be deduced (17.8.2) or obtained from default template-arguments may be omitted from the list of explicit template-arguments."

Am I wrong? Is the compiler wrong? Is this an oversight or a deliberate design?

template <typename T>
struct Foo {
    Foo(T t) {}
};

template <typename T1, typename T2>
struct Bar {
    Bar(T2 t) {}
};

template <typename T1, typename T2>
void bar(T2 t) {}

int main(int argc, char **argv) {

    Foo(42); // Works

    Bar<int>(42); // Fails to compile with "wrong number of
                  // template arguments (1, should be 2)"

    bar<int>(42); // Works
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
561 views
Welcome To Ask or Share your Answers For Others

1 Answer

This is expected behavior; unlike template argument deduction (for function templates), class template argument deduction (since C++17) only works when no template arguments are provided.

Class template argument deduction is only performed if no template arguments are provided. If at least one argument is specified, deduction does not take place.

std::tuple t(1, 2, 3);              // OK: deduction
std::tuple<int,int,int> t(1, 2, 3); // OK: all arguments are provided
std::tuple<int> t(1, 2, 3);         // Error: partial deduction

That means for your example you can't take advantage of class template argument deduction and have to specify all the template arguments. If you want class template argument deduction taking effect you have to specify none, but the template parameter T1 can't be deduced.

On the other hand, the following code would work.

template <typename T1, typename T2>
struct Bar {
    Bar(T1, T2) {}   // make it possible to deduce T1
};

int main(int argc, char **argv) {
    Bar bar(42, 42); // take advantage of class template argument deduction
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...