简体   繁体   中英

partial ordering variadic template function clang

I am currently playing on a project using Boost.ProgramOptions and I had to create the following structure to add some constraints on an option:

template <const char *str1, const char*... str2> 
struct restrictedValues
{
...
};

In order to validate that new option you must overload the boost::program_options::validate function:

template<class T, class charT>                                                                            
void validate(boost::any& v, const std::vector< std::basic_string<charT> >& xs, T*, long);

The call for this validate function is the following:

validate(value_store, new_tokens, (T*)0, 0);

As precised by boost: "The target type is specified via a parameter which has the type of pointer to the desired type. This is workaround for compilers without partial template ordering, just like the last 'long/int' parameter."

I, hence, wrote my validate version in the following way:

template<class charT, const char *... str>
void validate(boost::any &v,
        const std::vector<std::basic_string<charT> >& values,
        restrictedValues<str...>* /*target_type*/,
        int /*unused*/) { ... }

It looks like my version of clang (Ubuntu clang version 3.5.0-4ubuntu2~trusty2 (tags/RELEASE_350/final) (based on LLVM 3.5.0)) simply skip my version and gracefully fail in the default version. Whilst my gcc ((Ubuntu 4.8.2-19ubuntu1) 4.8.2) happily compile.

EDIT See a live example that shows the different behaviour, credits @dyp:

Live On Coliru

#include <boost/any.hpp>
#include <vector>
#include <string>
#include <iostream>

template <const char *str1, const char*... str2> struct restrictedValues                                                                                
{
/*...*/
};

template<class T, class charT>                                                                            
void validate(boost::any&, const std::vector< std::basic_string<charT> >&, T*, long)
{
    std::cout << "default version\n";
}

extern char const client[] = "hello";
extern char const server[] = "world";

template<class charT, const char *... str>
void validate(boost::any &,
        const std::vector<std::basic_string<charT> >&,
        restrictedValues<str...>* /*target_type*/,
        int /*unused*/) {
    std::cout << "custom version\n";
}

int main()
{
    boost::any a;
    std::vector<std::string> xs;
    restrictedValues<client, server>* p = 0;
    validate(a, xs, p, 0);
}

Moreover the same process using non-variadic templates (a fixed number of const char*) for the structure/function does work like a charm.

I am not quite sure which lookup process leads to such a ambiguous error. If my function didn't use template, it would be selected according to the overloading rules, but that isn't the case. By reading the partial ordering rules for template functions, both functions have the same specialization for the template parameters, but my expectation would be that the int/long trick should work. Any idea on how to solve this template mystery?

The usual approach here is to make ADL work using strong typedefs.

I've documented this in an older answer¹:


¹ the first comments there are obsolete and refer to the old answer I had before.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM