mirror of https://github.com/swig/swig
Consistency in warnings for ambiguous/redefined templated constructors
Constructors used to warn with: Warning 302: Identifier 'Json' redefined (ignored) But now warn with: Warning 322: Redundant redeclaration of 'Json' Note that 320 is a warning that is shown by default and 322 is a hidden warning by default. The warning is now consistent for both templated methods and constructors that are deemed redefined. See cpp11_template_parameters_decltype testcase. This testcase has been enhanced with a runtime test to check that the workarounds for overloaded templated constructors/methods do work.
This commit is contained in:
parent
44fcdbd290
commit
94ab699075
|
@ -1,9 +1,5 @@
|
||||||
%module cpp11_template_parameters_decltype
|
%module cpp11_template_parameters_decltype
|
||||||
|
|
||||||
%include <std_string.i>
|
|
||||||
%include <std_vector.i>
|
|
||||||
%include <std_pair.i>
|
|
||||||
|
|
||||||
%inline %{
|
%inline %{
|
||||||
// Github issue #1589
|
// Github issue #1589
|
||||||
template <decltype(true) X = true>
|
template <decltype(true) X = true>
|
||||||
|
@ -13,33 +9,99 @@ void A() { }
|
||||||
// %template(A) A<>; // not working
|
// %template(A) A<>; // not working
|
||||||
%template(A) A<true>; // workaround
|
%template(A) A<true>; // workaround
|
||||||
|
|
||||||
|
|
||||||
|
%include <std_string.i>
|
||||||
|
%include <std_vector.i>
|
||||||
|
%include <std_map.i>
|
||||||
|
|
||||||
#pragma SWIG nowarn=SWIGWARN_CPP11_DECLTYPE
|
#pragma SWIG nowarn=SWIGWARN_CPP11_DECLTYPE
|
||||||
|
|
||||||
// Non-template expression equivalent to template expression further down:
|
%{
|
||||||
%inline %{
|
// Simple implementation of helper functions required in test below
|
||||||
#include <utility>
|
std::string array(std::vector<std::string>::const_iterator begin, std::vector<std::string>::const_iterator end) {
|
||||||
#include <vector>
|
return "not implemented";
|
||||||
void f(bool c = std::is_constructible<std::string, decltype(std::declval<std::vector<std::pair<int, int>>>().begin()->first)>::value) {}
|
}
|
||||||
|
std::string object(std::map<std::string, std::string>::const_iterator begin, std::map<std::string, std::string>::const_iterator end) {
|
||||||
|
return "not implemented";
|
||||||
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%inline %{
|
%inline %{
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
// Github issue #1590
|
// Github issue #1590
|
||||||
struct Converter {
|
struct Converter {
|
||||||
std::string to_json() const { return std::string(); }
|
std::string to_json() const { return std::string(); }
|
||||||
};
|
};
|
||||||
struct Json {
|
struct Json {
|
||||||
Json(std::string s) {}
|
int ctor;
|
||||||
|
Json(std::string s) : ctor(0) {}
|
||||||
template < class T, class = decltype(&T::to_json) >
|
template < class T, class = decltype(&T::to_json) >
|
||||||
Json(const T & t) : Json(t.to_json()) {}
|
Json(const T & t) : Json(t.to_json()) { ctor = 1; }
|
||||||
|
|
||||||
// Github issue #1589
|
// Github issue #1589
|
||||||
// Implicit constructor: map-like objects (std::map, std::unordered_map, etc)
|
// Implicit constructor: map-like objects (std::map, std::unordered_map, etc)
|
||||||
template <class M, typename std::enable_if<
|
template <class M, typename std::enable_if<
|
||||||
std::is_constructible<std::string, decltype(std::declval<M>().begin()->first)>::value,
|
std::is_constructible<std::string, decltype(std::declval<M>().begin()->first)>::value,
|
||||||
int>::type = 0>
|
int>::type = 0>
|
||||||
Json(const M & m) : Json(object(m.begin(), m.end())) {}
|
Json(const M & m) : Json(object(m.begin(), m.end())) { ctor = 2; }
|
||||||
|
// Implicit constructor: vector-like objects (std::list, std::vector, std::set, etc)
|
||||||
|
template <class V, typename std::enable_if<
|
||||||
|
std::is_constructible<Json, decltype(*std::declval<V>().begin())>::value,
|
||||||
|
int>::type = 0>
|
||||||
|
Json(const V & v) : Json(array(v.begin(), v.end())) { ctor = 3; }
|
||||||
|
|
||||||
|
// Same sort of thing as constructors above but for a member function
|
||||||
|
int mmm(std::string s) { return 100; }
|
||||||
|
template < class T, class = decltype(&T::to_json) >
|
||||||
|
int mmm(const T & t) { return 101; }
|
||||||
|
template <class M, typename std::enable_if<
|
||||||
|
std::is_constructible<std::string, decltype(std::declval<M>().begin()->first)>::value,
|
||||||
|
int>::type = 0>
|
||||||
|
int mmm(const M & m) { return 102; }
|
||||||
|
template <class V, typename std::enable_if<
|
||||||
|
std::is_constructible<Json, decltype(*std::declval<V>().begin())>::value,
|
||||||
|
int>::type = 0>
|
||||||
|
int mmm(const V & v) { return 103; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void tester(bool show) {
|
||||||
|
// Example usage from c++
|
||||||
|
if (show) {
|
||||||
|
Json json0(std::string("hi"));
|
||||||
|
Converter converter;
|
||||||
|
std::cout << "json0 " << json0.ctor << std::endl;
|
||||||
|
Json json1 = Json(converter);
|
||||||
|
std::cout << "json1 " << json1.ctor << std::endl;
|
||||||
|
std::map<std::string, std::string> myStringStringMap;
|
||||||
|
Json json2 = Json(myStringStringMap);
|
||||||
|
std::cout << "json2 " << json2.ctor << std::endl;
|
||||||
|
std::vector<std::string> myVectorString;
|
||||||
|
Json json3 = Json(myVectorString);
|
||||||
|
std::cout << "json3 " << json3.ctor << std::endl;
|
||||||
|
|
||||||
|
std::cout << "json0.mmm " << json0.mmm("bye") << std::endl;
|
||||||
|
std::cout << "json1.mmm " << json1.mmm(converter) << std::endl;
|
||||||
|
std::cout << "json2.mmm " << json2.mmm(myStringStringMap) << std::endl;
|
||||||
|
std::cout << "json3.mmm " << json3.mmm(myVectorString) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
%template(VectorString) std::vector<std::string>;
|
||||||
|
%template(MapStringString) std::map<std::string, std::string>;
|
||||||
|
|
||||||
|
// There is quite a bit of inconsistency about providing or not providing default
|
||||||
|
// template parameters that needs investigating. Below is a combination that works.
|
||||||
|
|
||||||
|
// Note that instantiating the two Json constructors (or the two mmm methods) that
|
||||||
|
// use enable_if is ambiguous given the enable_if is not evaluated by SWIG.
|
||||||
|
|
||||||
// %template(Json) Json::Json<Converter>; // not working
|
// %template(Json) Json::Json<Converter>; // not working
|
||||||
%template(Json) Json::Json<Converter, std::string>; // workaround
|
%template(Json) Json::Json<Converter, std::string>; // workaround
|
||||||
|
%template(Json) Json::Json<std::map<std::string, std::string>, 0>;
|
||||||
|
%template(Json) Json::Json<std::vector<std::string>, 0>;
|
||||||
|
|
||||||
|
%template(mmm) Json::mmm<Converter, std::string>;
|
||||||
|
%template(mmm) Json::mmm<std::map<std::string, std::string>, 0>;
|
||||||
|
%template(mmm) Json::mmm<std::vector<std::string>, 0>;
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
import cpp11_template_parameters_decltype.*;
|
||||||
|
|
||||||
|
public class cpp11_template_parameters_decltype_runme {
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
System.loadLibrary("cpp11_template_parameters_decltype");
|
||||||
|
} catch (UnsatisfiedLinkError e) {
|
||||||
|
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String argv[]) {
|
||||||
|
boolean show = false; // for debugging
|
||||||
|
|
||||||
|
cpp11_template_parameters_decltype.tester(show);
|
||||||
|
Json json0 = new Json("hi");
|
||||||
|
if (json0.getCtor() != 0)
|
||||||
|
throw new RuntimeException("json0 failed");
|
||||||
|
if (json0.mmm("bye") != 100)
|
||||||
|
throw new RuntimeException("json0.mmm failed");
|
||||||
|
|
||||||
|
Converter converter = new Converter();
|
||||||
|
Json json1 = new Json(converter);
|
||||||
|
if (json1.getCtor() != 1)
|
||||||
|
throw new RuntimeException("json1 failed");
|
||||||
|
if (json1.mmm(converter) != 101)
|
||||||
|
throw new RuntimeException("json1.mmm failed");
|
||||||
|
|
||||||
|
MapStringString myMapStringString = new MapStringString();
|
||||||
|
Json json2 = new Json(myMapStringString);
|
||||||
|
if (json2.getCtor() != 2)
|
||||||
|
throw new RuntimeException("json2 failed");
|
||||||
|
if (json2.mmm(myMapStringString) != 102)
|
||||||
|
throw new RuntimeException("json2.mmm failed");
|
||||||
|
|
||||||
|
VectorString myVectorString = new VectorString();
|
||||||
|
Json json3 = new Json(myVectorString);
|
||||||
|
if (json3.getCtor() != 3)
|
||||||
|
throw new RuntimeException("json3 failed");
|
||||||
|
if (json3.mmm(myVectorString) != 103)
|
||||||
|
throw new RuntimeException("json3.mmm failed");
|
||||||
|
}
|
||||||
|
}
|
|
@ -972,8 +972,8 @@ static int nodes_are_equivalent(Node *a, Node *b, int a_inclass) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Cmp(ta, "cdecl") == 0) {
|
if (Equal(ta, "cdecl") || Equal(ta, "constructor")) {
|
||||||
/* both cdecl case */
|
/* both cdecl or constructor case */
|
||||||
/* typedef */
|
/* typedef */
|
||||||
String *a_storage = Getattr(a, "storage");
|
String *a_storage = Getattr(a, "storage");
|
||||||
String *b_storage = Getattr(b, "storage");
|
String *b_storage = Getattr(b, "storage");
|
||||||
|
|
Loading…
Reference in New Issue