GCC 4.9 ambiguous overload template specialization - c++

I'm running into an issue with gcc 4.9.2 (with -std=c++11) not compiling a piece of code with the error message being
call of overloaded 'InsertDataIntoInputMap(int&, boost::shared_ptr&)' is ambiguous
The code does compile with msvc 2013
#include <iostream>
#include <map>
#include <boost/shared_ptr.hpp>
struct Proxy
{
typedef std::map<int, int> InputDataMap;
int a;
};
template<class C, class D>
void InsertDataIntoInputMap(
const typename C::InputDataMap::key_type& key,
const D val)
{
std::cout << "Not shared\n";
}
template<class C, class D>
void InsertDataIntoInputMap(
const typename C::InputDataMap::key_type& key,
const boost::shared_ptr<D> val)
{
if (val)
{
std::cout << "Shared\n";
}
}
int main() {
int a;
boost::shared_ptr<double> x(new double(4.5));
InsertDataIntoInputMap<Proxy>(a, x);
}
while the following does actually compile with both gcc and msvc:
#include <iostream>
#include <boost/shared_ptr.hpp>
template<class C, class D>
void InsertDataIntoInputMap(
const C& key,
const D val)
{
std::cout << "Not shared\n";
}
template<class C, class D>
void InsertDataIntoInputMap(
const C& key,
const boost::shared_ptr<D> val)
{
if (val)
{
std::cout << "Shared\n";
}
}
int main() {
int a = 0;
boost::shared_ptr<double> x(new double(4.5));
InsertDataIntoInputMap<int>(a, x);
return 0;
}
I would have thought that the compiler should take the function with the boost::shared_ptr argument in both cases?

This problem can be reduced to an imprecision in partial ordering: Pairs in which no template-parameters appear that are involved in deduction are still considered and compaired. That issue was addressed by CWG #455 and #885 as well.
In your example, overload resolution isn't able to distinguish the overloads. Hence partial ordering is necessary. And partial ordering will try to perform deduction twice, with the parameter type P being typename C::InputDataMap::key_type.
However, that deduction is doomed to fail, since C solely appears in a non-deduced context. I.e. the type from both templates (for that particular pair) is not at least as specialized as the type from the respective other template - and that, in turn, implies that neither of the templates is more specialized than the other.
As noted by #T.C., the resolution of CWG #1391 helps. This part in particular:
Change 14.8.2.4 [temp.deduct.partial] paragraph 4 as follows:
Each type nominated above from the parameter template and the corresponding type from the argument template are used as the types of P and A. If a particular P contains no template-parameters that participate in template argument deduction, that P is not used to determine the ordering.
Now, the first parameter pair is entirely ignored in both ways (as the types of C are solely determined from the explicit argument list), and the second overload is found to be more specialized.

A simple alias can make that code work:
#include <iostream>
#include <map>
#include <boost/shared_ptr.hpp>
struct Proxy
{
typedef std::map<int, int> InputDataMap;
int a;
};
template<class C, class D, class F = typename C::InputDataMap::key_type>
void InsertDataIntoInputMap(
const F& key,
const D val)
{
std::cout << "Not shared\n";
}
template<class C, class D, class F = typename C::InputDataMap::key_type>
void InsertDataIntoInputMap(
const F& key,
const boost::shared_ptr<D> val)
{
if (val)
{
std::cout << "Shared\n";
}
}
int main() {
int a;
boost::shared_ptr<double> x(new double(4.5));
InsertDataIntoInputMap<Proxy>(a, x);
}
But imo. this shouldn't work, cause I thought, the draft says, the compiler will not consider the C::InputDataMap - Namespace in
class F = typename C::InputDataMap::key_type
and F will be a non-deduced context (like key_type).

Related

C++ MSVC/GCC/Clang compilers bug

I discovered what appears to be a mind breaking bug in the 3 compilers from the title. The following code compiles with the latest versions of all three compilers using both the c++11 and c++14 standards, even though it really shouldn't as the "visit_detail" function is not visible to "main".
Correction: I was stupid, not actually a bug in GCC/Clang, seems to be a bug in my MSVC version tho.
#include <utility>
#include <iostream>
#include <type_traits>
namespace bug
{
using namespace std;
using size_t = unsigned long long;
namespace detail
{
struct visit_stop_t {};
constexpr bug::detail::visit_stop_t visit_stop = bug::detail::visit_stop_t();
template <typename Visitor, typename First, typename... Tail>
void visit_detail(Visitor&& vis, First&& first, Tail&&... tail)
{
// code, not necessairy to recreate bug
}
}
template <typename Visitor, typename... Variants>
void visit(Visitor&& vis, Variants&&... vars)
{
bug::detail::visit_detail(bug::forward<Visitor>(vis), bug::forward<Variants>(vars)..., bug::detail::visit_stop);
}
template <typename Visitor>
void visit(Visitor&& vis) = delete;
}
using namespace bug;
// dummy variant, used to test the code
// code is never actually used in this version
template <typename... T>
struct variant
{
static constexpr bug::size_t size() noexcept { return sizeof...(T); }
constexpr variant(int) noexcept {}
template <bug::size_t I>
constexpr int get() const noexcept { return 5; }
};
// simple example visitor
// code is never actually used in this version
struct visitor
{
int operator()(int x) { std::cout << x << std::endl; return x; }
double operator()(double x) { std::cout << x << std::endl; return x; }
};
int main()
{
visitor vis;
variant<int, double> var = 5;
// where the trouble is:
visit_detail(vis, var, bug::detail::visit_stop); // ADL: http://en.cppreference.com/w/cpp/language/adl
visit_detail(vis, var); // fails with GCC/Clang, no error with MSVC => MSVC bug maybe
std::cout << "Press enter to continue . . . ";
std::getchar();
return 0;
}
What you're experiencing is a C++ feature called argument-dependent lookup, or ADL for short. Basically, if you invoke a function f without explicitly qualifying it, the compiler will look for f in the namespaces of the arguments that you've passed.
This is what allows operator<< for IO streams to work without requiring qualifications:
std::cout << 100; // finds std::operator<<(std::ostream&, int);
In your particular case, the argument bug::detail::visit_stop is making the compiler look for visit_detail inside the bug::detail namespace.

Static constants of templated class

I have been playing around with template classes and constants in gcc 4.8.2 and came across an interesting linker error:
#include <iostream>
using namespace std;
template <class T, int m>
class A {
public:
static const T param = m;
T value;
A(const T &value, const T &dummy = T()) : value(value) {}
};
// Works with this
// template <class T, int m>
// const T A<T, m>::param = m;
template <class T, int m>
A<T, m> operator +(const A<T, m> &a, const A<T, m> &b) {
if (a.param != b.param) exit(1);
// Works if I replace a.param with 0
return A<T, m>(a.value + b.value, a.param);
}
int main() {
A<int, 2> v = A<int, 2>(1) + A<int, 2>(2);
cout << v.value << endl;
return 0;
}
Compiling the code in the current state gives a linker error, telling me that A::param is not defined.
Trying this code in Visual Studio 2008 as well, it compiles and links without any problems. On gcc, it compiles when I either use the external declaration of the param constant, or if I replace a.param with 0 or nothing on the line indicated.
What I do not understand is why the line containing the if statement can use a.param without compilation error, while I cannot pass a.param to the constructor without declaring it externally.
So my question is: When do I need to declare param externally, and what is the difference between the access in the if statement and the constructor call? Which of the two compilers I tested does the "right" thing here, and which one has extended the standard?
Playing around a little more, I realized it also works when I specify the -O2 flag to g++.
template <class T, int m>
class A {
public:
static const T param = m;
T value;
A(const T &value, const T &dummy = T()) : value(value) {}
};
// Works with this
// template <class T, int m>
// const T A<T, m>::param = m;
//gotta define it here!
template <class T, int m>
const T A<T, m>::param;
template <class T, int m>
A<T, m> operator +(const A<T, m> &a, const A<T, m> &b) {
if (a.param != b.param) exit(1);
// Works if I replace a.param with 0
return A<T, m>(a.value + b.value, a.param);
}
int main() {
A<int, 2> v = A<int, 2>(1) + A<int, 2>(2);
std::cout << v.value << std::endl;
return 0;
}
from here
If a static data member is of const integral or const enumeration type, you may specify a constant initializer in the static data member's declaration. This constant initializer must be an integral constant expression. Note that the constant initializer is not a definition. You still need to define the static member in an enclosing namespace.
In the cases that is working, the compilers are being non-compliant. Microsoft is non-compliant cuz Microsoft is almost never compliant, the g++ with -O2 is kinda funny, but in either case you've got no definition!
Edit:
As a rule of thumb, I always define my static constant member variables outside of the class because then I never have to remember it. In this case, class A would be invalid if T was anything other than an integral type, such as a float. So rather than do any patterns around the exception, I tend to just stick with my patterns around the rule.

Getting the C++ compiler to reveal what a type can be converted to

Below is a flawed (and simplified) template function that expects to work on a template arg that can be converted to one of a predefined number of types.
It happens to be 2 types, but it cold be many more.
void do_something_type_specific( const int &unused ) { std::cout << 'i'; }
void do_something_type_specific( const std::string &unused ) { std::cout << 's'; }
template< typename Iterator >
void perform_work_on_a_range( Iterator begin, Iterator end )
{
do_something_type_specific( *begin );
// Perhaps more code...
}
This happens to produce the desired results in my environment.
Template instances will compile successfully iff *Iterator produces a type that's convertible to exactly one of the choices.
However, this code unnecessarily requests that the conversion be performed and, despite unused being unused, there is still UB when begin == end.
How can this this behavior be implemented in C++03 without these problems?
Instead of dereferencing the iterator that my result in undefined behaviour when begin == end, you could try using std::iterator_traits<>. E.g.:
#include <iterator>
#include <string>
#include <cstdio>
void do_something_type_specific(std::string const&) { printf("%s\n", __PRETTY_FUNCTION__); }
void do_something_type_specific(int const&) { printf("%s\n", __PRETTY_FUNCTION__); }
template<class T>
struct ProduceValue
{
static T value;
};
template<class T>
T ProduceValue<T>::value;
// Specializations for types that can't be default constructed or must be initialized.
template<>
char* ProduceValue<char*>::value = "";
template< typename Iterator >
void perform_work_on_a_range( Iterator begin, Iterator end )
{
typedef typename std::iterator_traits<Iterator>::value_type value_type;
do_something_type_specific(ProduceValue<value_type>::value);
}
int main() {
char** p = 0;
perform_work_on_a_range(p, p);
long* q = 0;
perform_work_on_a_range(q, q);
}
Output:
void do_something_type_specific(const string&)
void do_something_type_specific(const int&)
The only inconvenience is that ProduceValue<T> has to be specialized for types that can't be default constructed or must be initialized for other reasons (like char*).
There is a boost::is_convertible metafunction that you can use to determine if a type T can be converted to some other type U.
Secondly, for begin == end, just insert a run-time check.
The problematic code in the question is trying to leverage features of both template parameters and function parameters.
Function parameters allow type conversions, but require an instantiation of the type. Template parameters don't need instantiation, but also don't perform type conversions.
The pattern below uses Boost's enable_if and is_convertible to allow template functions to be chosen by the compiler as if template parameters supported the same type conversion rules as function parameters. (Thank #dhavenith for the suggestion)
#include <boost/utility.hpp>
#include <boost/type_traits.hpp>
// enable_if_c makes the return type either void or a Substitution Failure.
template < typename T>
typename boost::enable_if_c<boost::is_convertible<T,int>::value>::type
do_something_type_specific()
{
std::cout << 'i';
}
template < typename T>
typename boost::enable_if_c<boost::is_convertible<T,std::string>::value>::type
do_something_type_specific()
{
std::cout << 's';
}
template< typename Iterator >
void perform_work_on_a_range( Iterator begin, Iterator end )
{
// This code is from #MaximYegorushkin's answer. Vote him up :)
typedef typename std::iterator_traits<Iterator>::value_type value_type;
do_something_type_specific<value_type>();
// Perhaps more code...
}
This has been verified with #MaximYegorushkin's sample main.
int main() {
char** p = 0;
perform_work_on_a_range(p, p);
long* q = 0;
perform_work_on_a_range(q, q);
}
Output:
si
You probably want to do something like this instead:
template <typename T>
void do_something_type_specific() {}
template <>
void do_something_type_specific<int>() {...}
template <typename Iterator>
void perform_work_on_a_range(Iterator begin, Iterator end) {
do_something_type_specific<typename Iterator::value_type>();
}

Passing an integer or a type as a template parameter?

Here is an example case of what I'm trying to do (it is a "test" case just to illustrate the problem) :
#include <iostream>
#include <type_traits>
#include <ratio>
template<int Int, typename Type>
constexpr Type f(const Type x)
{
return Int*x;
}
template<class Ratio, typename Type,
class = typename std::enable_if<Ratio::den != 0>::type>
constexpr Type f(const Type x)
{
return (x*Ratio::num)/Ratio::den;
}
template</*An int OR a type*/ Something, typename Type>
constexpr Type g(const Type x)
{
return f<Something, Type>(x);
}
int main()
{
std::cout<<f<1>(42.)<<std::endl;
std::cout<<f<std::kilo>(42.)<<std::endl;
}
As you can see, there are two versions of the f() function : the first one takes an int as a template parameter, and the second one takes a std::ratio. The problem is the following :
I would like to "wrap" this function through g() which can take an int OR a std::ratio as first template parameter and call the good version of f().
How to do that without writing two g() functions ? In other words, what do I have to write instead of /*An int OR a type*/ ?
Here's how I would do it, but I've changed your interface slightly:
#include <iostream>
#include <type_traits>
#include <ratio>
template <typename Type>
constexpr
Type
f(int Int, Type x)
{
return Int*x;
}
template <std::intmax_t N, std::intmax_t D, typename Type>
constexpr
Type
f(std::ratio<N, D> r, Type x)
{
// Note use of r.num and r.den instead of N and D leads to
// less probability of overflow. For example if N == 8
// and D == 12, then r.num == 2 and r.den == 3 because
// ratio reduces the fraction to lowest terms.
return x*r.num/r.den;
}
template <class T, class U>
constexpr
typename std::remove_reference<U>::type
g(T&& t, U&& u)
{
return f(static_cast<T&&>(t), static_cast<U&&>(u));
}
int main()
{
constexpr auto h = g(1, 42.);
constexpr auto i = g(std::kilo(), 42.);
std::cout<< h << std::endl;
std::cout<< i << std::endl;
}
42
42000
Notes:
I've taken advantage of constexpr to not pass compile-time constants via template parameters (that's what constexpr is for).
g is now just a perfect forwarder. However I was unable to use std::forward because it isn't marked up with constexpr (arguably a defect in C++11). So I dropped down to use static_cast<T&&> instead. Perfect forwarding is a little bit overkill here. But it is a good idiom to be thoroughly familiar with.
How to do that without writing two g() functions ?
You don't. There is no way in C++ to take either a type or a value of some type, except through overloading.
It is not possible to have a template parameter taking both type and non-type values.
Solution 1:
Overloaded functions.
Solution 2:
You can store values in types. Ex:
template<int n>
struct store_int
{
static const int num = n;
static const int den = 1;
};
template<class Ratio, typename Type,
class = typename std::enable_if<Ratio::den != 0>::type>
constexpr Type f(const Type x)
{
return (x*Ratio::num)/Ratio::den;
}
template<typename Something, typename Type>
constexpr Type g(const Type x)
{
return f<Something, Type>(x);
}
But with this solution you will have to specify g<store_int<42> >(...) instead of g<42>(...)
If the function is small, I advise you to use overloading.

How do I avoid implicit conversions on non-constructing functions?

How do I avoid implicit casting on non-constructing functions?
I have a function that takes an integer as a parameter,
but that function will also take characters, bools, and longs.
I believe it does this by implicitly casting them.
How can I avoid this so that the function only accepts parameters of a matching type, and will refuse to compile otherwise?
There is a keyword "explicit" but it does not work on non-constructing functions. :\
what do I do?
The following program compiles, although I'd like it not to:
#include <cstdlib>
//the function signature requires an int
void function(int i);
int main(){
int i{5};
function(i); //<- this is acceptable
char c{'a'};
function(c); //<- I would NOT like this to compile
return EXIT_SUCCESS;
}
void function(int i){return;}
*please be sure to point out any misuse of terminology and assumptions
Define function template which matches all other types:
void function(int); // this will be selected for int only
template <class T>
void function(T) = delete; // C++11
This is because non-template functions with direct matching are always considered first. Then the function template with direct match are considered - so never function<int> will be used. But for anything else, like char, function<char> will be used - and this gives your compilation errrors:
void function(int) {}
template <class T>
void function(T) = delete; // C++11
int main() {
function(1);
function(char(1)); // line 12
}
ERRORS:
prog.cpp: In function 'int main()':
prog.cpp:4:6: error: deleted function 'void function(T) [with T = char]'
prog.cpp:12:20: error: used here
This is C++03 way:
// because this ugly code will give you compilation error for all other types
class DeleteOverload
{
private:
DeleteOverload(void*);
};
template <class T>
void function(T a, DeleteOverload = 0);
void function(int a)
{}
You can't directly, because a char automatically gets promoted to int.
You can resort to a trick though: create a function that takes a char as parameter and don't implement it. It will compile, but you'll get a linker error:
void function(int i)
{
}
void function(char i);
//or, in C++11
void function(char i) = delete;
Calling the function with a char parameter will break the build.
See http://ideone.com/2SRdM
Terminology: non-construcing functions? Do you mean a function that is not a constructor?
8 years later (PRE-C++20, see edit):
The most modern solution, if you don't mind template functions -which you may mind-, is to use a templated function with std::enable_if and std::is_same.
Namely:
// Where we want to only take int
template <class T, std::enable_if_t<std::is_same_v<T,int>,bool> = false>
void func(T x) {
}
EDIT (c++20)
I've recently switched to c++20 and I believe that there is a better way. If your team or you don't use c++20, or are not familiar with the new concepts library, do not use this. This is much nicer and the intended method as outlines in the new c++20 standard, and by the writers of the new feature (read a papers written by Bjarne Stroustrup here.
template <class T>
requires std::same_as(T,int)
void func(T x) {
//...
}
Small Edit (different pattern for concepts)
The following is a much better way, because it explains your reason, to have an explicit int. If you are doing this frequently, and would like a good pattern, I would do the following:
template <class T>
concept explicit_int = std::same_as<T,int>;
template <explicit_int T>
void func(T x) {
}
Small edit 2 (the last I promise)
Also a way to accomplish this possibility:
template <class T>
concept explicit_int = std::same_as<T,int>;
void func(explicit_int auto x) {
}
Here's a general solution that causes an error at compile time if function is called with anything but an int
template <typename T>
struct is_int { static const bool value = false; };
template <>
struct is_int<int> { static const bool value = true; };
template <typename T>
void function(T i) {
static_assert(is_int<T>::value, "argument is not int");
return;
}
int main() {
int i = 5;
char c = 'a';
function(i);
//function(c);
return 0;
}
It works by allowing any type for the argument to function but using is_int as a type-level predicate. The generic implementation of is_int has a false value but the explicit specialization for the int type has value true so that the static assert guarantees that the argument has exactly type int otherwise there is a compile error.
Maybe you can use a struct to make the second function private:
#include <cstdlib>
struct NoCast {
static void function(int i);
private:
static void function(char c);
};
int main(){
int i(5);
NoCast::function(i); //<- this is acceptable
char c('a');
NoCast::function(c); //<- Error
return EXIT_SUCCESS;
}
void NoCast::function(int i){return;}
This won't compile:
prog.cpp: In function ‘int main()’:
prog.cpp:7: error: ‘static void NoCast::function(char)’ is private
prog.cpp:16: error: within this context
For C++14 (and I believe C++11), you can disable copy constructors by overloading rvalue-references as well:
Example:
Say you have a base Binding<C> class, where C is either the base Constraint class, or an inherited class. Say you are storing Binding<C> by value in a vector, and you pass a reference to the binding and you wish to ensure that you do not cause an implicit copy.
You may do so by deleting func(Binding<C>&& x) (per PiotrNycz's example) for rvalue-reference specific cases.
Snippet:
template<typename T>
void overload_info(const T& x) {
cout << "overload: " << "const " << name_trait<T>::name() << "&" << endl;
}
template<typename T>
void overload_info(T&& x) {
cout << "overload: " << name_trait<T>::name() << "&&" << endl;
}
template<typename T>
void disable_implicit_copy(T&& x) = delete;
template<typename T>
void disable_implicit_copy(const T& x) {
cout << "[valid] ";
overload_info<T>(x);
}
...
int main() {
Constraint c;
LinearConstraint lc(1);
Binding<Constraint> bc(&c, {});
Binding<LinearConstraint> blc(&lc, {});
CALL(overload_info<Binding<Constraint>>(bc));
CALL(overload_info<Binding<LinearConstraint>>(blc));
CALL(overload_info<Binding<Constraint>>(blc));
CALL(disable_implicit_copy<Binding<Constraint>>(bc));
// // Causes desired error
// CALL(disable_implicit_copy<Binding<Constraint>>(blc));
}
Output:
>>> overload_info(bc)
overload: T&&
>>> overload_info<Binding<Constraint>>(bc)
overload: const Binding<Constraint>&
>>> overload_info<Binding<LinearConstraint>>(blc)
overload: const Binding<LinearConstraint>&
>>> overload_info<Binding<Constraint>>(blc)
implicit copy: Binding<LinearConstraint> -> Binding<Constraint>
overload: Binding<Constraint>&&
>>> disable_implicit_copy<Binding<Constraint>>(bc)
[valid] overload: const Binding<Constraint>&
Error (with clang-3.9 in bazel, when offending line is uncommented):
cpp_quick/prevent_implicit_conversion.cc:116:8: error: call to deleted function 'disable_implicit_copy'
CALL(disable_implicit_copy<Binding<Constraint>>(blc));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Full Source Code: prevent_implicit_conversion.cc
Well, I was going to answer this with the code below, but even though it works with Visual C++, in the sense of producing the desired compilation error, MinGW g++ 4.7.1 accepts it, and invokes the rvalue reference constructor!
I think it must be a compiler bug, but I could be wrong, so – anyone?
Anyway, here's the code, which may turn out to be a standard-compliant solution (or, it may turn out that that's a thinko on my part!):
#include <iostream>
#include <utility> // std::is_same, std::enable_if
using namespace std;
template< class Type >
struct Boxed
{
Type value;
template< class Arg >
Boxed(
Arg const& v,
typename enable_if< is_same< Type, Arg >::value, Arg >::type* = 0
)
: value( v )
{
wcout << "Generic!" << endl;
}
Boxed( Type&& v ): value( move( v ) )
{
wcout << "Rvalue!" << endl;
}
};
void function( Boxed< int > v ) {}
int main()
{
int i = 5;
function( i ); //<- this is acceptable
char c = 'a';
function( c ); //<- I would NOT like this to compile
}
I first tried PiotrNycz's approach (for C++03, which I'm forced to use for a project), then I tried to find a more general approach and came up with this ForcedType<T> template class.
template <typename T>
struct ForcedType {
ForcedType(T v): m_v(v) {}
operator T&() { return m_v; }
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(T2);
T m_v;
};
template <typename T>
struct ForcedType<const T&> {
ForcedType(const T& v): m_v(v) {}
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(const T2&);
const T& m_v;
};
template <typename T>
struct ForcedType<T&> {
ForcedType(T& v): m_v(v) {}
operator T&() { return m_v; }
operator const T&() const { return m_v; }
private:
template <typename T2>
ForcedType(T2&);
T& m_v;
};
If I'm not mistaken, those three specializations should cover all common use cases. I'm not sure if a specialization for rvalue-reference (on C++11 onwards) is actually needed or the by-value one suffices.
One would use it like this, in case of a function with 3 parameters whose 3rd parameter doesn't allow implicit conversions:
function(ParamType1 param1, ParamType2 param2, ForcedType<ParamType3> param3);