Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
448 views
in Technique[技术] by (71.8m points)

c++ - Simple variadic template function can't instantinate

I'm aware that sizeof...(Args...) yields the number of types in a C++0x packed template argument list, but I wanted to implement it in terms of other features for demonstation purposes, but it won't compile.

// This is not a solution -- overload ambiguity.
// template <typename... Args> size_t num_args ();          // Line 7
// template <>
constexpr size_t num_args ()
{
    return 0;
}

template <typename H, typename... T>
constexpr size_t num_args ()                                // Line 16
{
    return 1 + num_args <T...> (); // *HERE*
}

int main ()
{
    std :: cout << num_args <int, int, int> ();
}

This errors at *HERE* with

No matching function call to ...
... candidate is template<class H, class ... T> size_t num_args()

i.e. it's not seeing the base case which is defined first. Forward-declaring template<typename...T>num_args(); introduces ambiguity in overload resolution.

x.cpp:30:45: note: candidates are:
x.cpp:7:36: note: size_t num_args() [with Args = {int, float, char}, size_t = long unsigned int]
x.cpp:16:9: note: size_t num_args() [with H = int, T = {float, char}, size_t = long unsigned int]

I am using gcc 4.6. How can I make this work?

Thanks.

See Question&Answers more detail:os

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

1 Reply

0 votes
by (71.8m points)

You didn’t declare a base case. You have a template-free overload of your num_args function but when calling a function num_args<T...>() this will never be found, for obvious reasons: it will always try to instantiate a function template.

You can however specialise your function template to perform the desired operation.

template <>
constexpr size_t num_args<>()
{
    return 0;
}

However, this won’t work either since here you’re specialising a parameterless function template and such a template doesn’t exist: your other function template num_args always has at least one argument, H.

In order to really make this work you need partial specialisations, and these only exist for class templates. So this is what you need here.

template <typename T>
struct num_args_t;

template <>
struct num_args_t {
    static size_t const value = 0;
};

template <typename H, typename T...>
struct num_args_t {
    static size_t const value = num_args_t<T...>::value + 1;
};

template <typename T...>
constexpr size_t num_args() {
    return num_args_t<T...>::value;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...