Search code examples
c++solarislanguage-features

Is the const value parameter in definition but not declaration really C++?


This is similar to (but different from) this question.

Here is some simple test code to illustrate some weirdness I have discovered with Sun CC:

//---------------main.cpp
#include "wtc.hpp"

int main(int, char**)
{
  testy t;
  t.lame(99);
  return 0;
}
//--------------wtc.hpp
#ifndef WTC_HPP_INCLUDED
#define WTC_HPP_INCLUDED

class testy
{
public:
  void lame(int );
};

#endif 

//---------------wtc.cpp
#include <iostream>
#include "wtc.hpp"

void testy::lame(const int a)
{
  std::cout << "I was passed " << a << "\n";
}

//---------------makefile
#CXX=CC
CXX =g++
#CXXFLAGS= -g 
CXXFLAGS= -g3 -Wall -Werror

OBJECTS=$(patsubst %.cpp,%.o,$(wildcard *.cpp))

all : $(OBJECTS)
    $(CXX) $(CXXFLAGS) -o $@ $^

.PHONY: clean
clean :
    rm *.o

When this was compiled using g++ it compiles, links and does what you would expect when run. You can also add a ++a; in testy::lame() and the compiler will complain about changing a read-only variable (as it should).

However when I compile using CC, I get the following linker error:

CC -g   -c -o main.o main.cpp
CC -g   -c -o wtc.o wtc.cpp
CC -g -o all main.o wtc.o
Undefined                       first referenced
 symbol                             in file
void testy::lame(int)               main.o
ld: fatal: Symbol referencing errors. No output written to all
make: *** [all] Error 1

checking the object code with nm and C++filt, I find that the g++ version creates a testy::lame(int) symbol, whereas CC creates testy::lame(const int) , hence the linker error.

I looked it up in Stroustrup's book, but can't find this technique mentioned (doesn't mean it's not there!); so is this really a compiler bug, or just a hack that works everywhere else but Solaris?


Solution

  • This looks like a compiler problem in CC. The C++ standard says (in 13.1 Overloadable declarations):

    Parameter declarations that differ only in the presence or absence of const and/or volatile are equivalent. That is, the const and volatile type-specifiers for each parameter type are ignored when determining which function is being declared, defined, or called.

    But there are const/volatile modifiers that can participate in overloading, as the standard mentions shortly afterwards:

    Only the const and volatile type-specifiers at the outermost level of the parameter type specification are ignored in this fashion; const and volatile type-specifiers buried within a parameter type specification are significant and can be used to distinguish overloaded function declarations.